diff --git a/.buildkite/ftr_oblt_stateful_configs.yml b/.buildkite/ftr_oblt_stateful_configs.yml index 5972264018aa3..729c5505915ab 100644 --- a/.buildkite/ftr_oblt_stateful_configs.yml +++ b/.buildkite/ftr_oblt_stateful_configs.yml @@ -6,10 +6,7 @@ disabled: - x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_config.ts - x-pack/solutions/observability/plugins/inventory/e2e/ftr_config_run.ts - x-pack/solutions/observability/plugins/inventory/e2e/ftr_config.ts - - x-pack/solutions/observability/plugins/profiling/e2e/ftr_config_open.ts - - x-pack/solutions/observability/plugins/profiling/e2e/ftr_config_runner.ts - - x-pack/solutions/observability/plugins/profiling/e2e/ftr_config.ts - + - x-pack/test/profiling_cypress/cli_config.ts #FTR configs - x-pack/solutions/observability/plugins/uptime/e2e/config.ts @@ -31,7 +28,6 @@ enabled: - x-pack/test/api_integration/apis/synthetics/config.ts - x-pack/test/api_integration/apis/uptime/config.ts - x-pack/test/api_integration/apis/entity_manager/config.ts - - x-pack/test/api_integration/apis/streams/config.ts - x-pack/test/apm_api_integration/basic/config.ts - x-pack/test/apm_api_integration/cloud/config.ts - x-pack/test/apm_api_integration/rules/config.ts diff --git a/.buildkite/ftr_security_stateful_configs.yml b/.buildkite/ftr_security_stateful_configs.yml index b650affb99227..d9953cfe1e727 100644 --- a/.buildkite/ftr_security_stateful_configs.yml +++ b/.buildkite/ftr_security_stateful_configs.yml @@ -105,3 +105,4 @@ enabled: - x-pack/test/cloud_security_posture_functional/data_views/config.ts - x-pack/test/automatic_import_api_integration/apis/config_basic.ts - x-pack/test/automatic_import_api_integration/apis/config_graphs.ts + - x-pack/test/security_solution_api_integration/test_suites/asset_inventory/entity_store/trial_license_complete_tier/configs/ess.config.ts diff --git a/.buildkite/package-lock.json b/.buildkite/package-lock.json index 077986e3d636b..e9017b545e468 100644 --- a/.buildkite/package-lock.json +++ b/.buildkite/package-lock.json @@ -17,7 +17,7 @@ }, "devDependencies": { "@types/chai": "^4.3.3", - "@types/js-yaml": "^4.0.5", + "@types/js-yaml": "^4.0.9", "@types/minimatch": "^3.0.5", "@types/mocha": "^10.0.1", "@types/node": "^15.12.2", @@ -354,9 +354,9 @@ "dev": true }, "node_modules/@types/js-yaml": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", - "integrity": "sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", "dev": true }, "node_modules/@types/minimatch": { @@ -2215,9 +2215,9 @@ "dev": true }, "@types/js-yaml": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", - "integrity": "sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", "dev": true }, "@types/minimatch": { diff --git a/.buildkite/package.json b/.buildkite/package.json index 9edd3b330b0ed..3c7fe28d0c064 100644 --- a/.buildkite/package.json +++ b/.buildkite/package.json @@ -19,7 +19,7 @@ }, "devDependencies": { "@types/chai": "^4.3.3", - "@types/js-yaml": "^4.0.5", + "@types/js-yaml": "^4.0.9", "@types/minimatch": "^3.0.5", "@types/mocha": "^10.0.1", "@types/node": "^15.12.2", diff --git a/.buildkite/pipelines/on_merge.yml b/.buildkite/pipelines/on_merge.yml index c52f3ac6687a9..04a025d99b503 100644 --- a/.buildkite/pipelines/on_merge.yml +++ b/.buildkite/pipelines/on_merge.yml @@ -479,6 +479,22 @@ steps: - exit_status: '-1' limit: 1 + - command: .buildkite/scripts/steps/functional/profiling_cypress.sh + label: 'Profiling Cypress Tests' + agents: + image: family/kibana-ubuntu-2004 + imageProject: elastic-images-prod + provider: gcp + machineType: n2-standard-4 + preemptible: true + depends_on: build + timeout_in_minutes: 120 + parallelism: 3 + retry: + automatic: + - exit_status: '-1' + limit: 1 + - command: .buildkite/scripts/steps/functional/apm_cypress.sh label: 'APM Cypress Tests' agents: diff --git a/.buildkite/pipelines/on_merge_unsupported_ftrs.yml b/.buildkite/pipelines/on_merge_unsupported_ftrs.yml index 78b3d6b44200c..42ab2e9271e19 100644 --- a/.buildkite/pipelines/on_merge_unsupported_ftrs.yml +++ b/.buildkite/pipelines/on_merge_unsupported_ftrs.yml @@ -28,25 +28,6 @@ steps: - exit_status: '-1' limit: 3 - - command: .buildkite/scripts/steps/functional/profiling_cypress.sh - label: 'Profiling Cypress Tests' - agents: - image: family/kibana-ubuntu-2004 - imageProject: elastic-images-prod - provider: gcp - machineType: n2-standard-4 - preemptible: true - depends_on: build - env: - PING_SLACK_TEAM: "@obs-ux-infra_services-team" - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - command: .buildkite/scripts/steps/functional/synthetics_plugin.sh label: 'Synthetics @elastic/synthetics Tests' agents: diff --git a/.buildkite/pipelines/pull_request/profiling_cypress.yml b/.buildkite/pipelines/pull_request/profiling_cypress.yml index 8ed98a4fbc736..3f77f8811d8c0 100644 --- a/.buildkite/pipelines/pull_request/profiling_cypress.yml +++ b/.buildkite/pipelines/pull_request/profiling_cypress.yml @@ -13,7 +13,7 @@ steps: - check_types - check_oas_snapshot timeout_in_minutes: 120 - parallelism: 2 + parallelism: 3 retry: automatic: - exit_status: '-1' diff --git a/.buildkite/scripts/steps/functional/profiling_cypress.sh b/.buildkite/scripts/steps/functional/profiling_cypress.sh index 318d45d0b125d..cf93715f8cc3a 100644 --- a/.buildkite/scripts/steps/functional/profiling_cypress.sh +++ b/.buildkite/scripts/steps/functional/profiling_cypress.sh @@ -2,17 +2,15 @@ set -euo pipefail -source .buildkite/scripts/common/util.sh +source .buildkite/scripts/steps/functional/common.sh -.buildkite/scripts/bootstrap.sh -.buildkite/scripts/download_build_artifacts.sh -.buildkite/scripts/copy_es_snapshot_cache.sh +export KIBANA_INSTALL_DIR=${KIBANA_BUILD_LOCATION} export JOB=kibana-profiling-cypress echo "--- Profiling Cypress Tests" -cd "$XPACK_DIR" +cd "$XPACK_DIR/solutions/observability/plugins/profiling/e2e" -NODE_OPTIONS=--openssl-legacy-provider node solutions/observability/plugins/profiling/scripts/test/e2e.js \ - --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ \ No newline at end of file +set +e +yarn cypress:run; status=$?; yarn junit:merge || :; exit $status diff --git a/.buildkite/scripts/steps/package_testing/test.sh b/.buildkite/scripts/steps/package_testing/test.sh index c16d5cf98b5f5..0bbfc21b7bb9e 100755 --- a/.buildkite/scripts/steps/package_testing/test.sh +++ b/.buildkite/scripts/steps/package_testing/test.sh @@ -5,8 +5,9 @@ set -euo pipefail source "$(dirname "$0")/../../common/util.sh" .buildkite/scripts/bootstrap.sh -# temporary adding this to get screenshots -is_test_execution_step +# temporary enable this to get screenshots on package testing failures +# +#is_test_execution_step echo "--- Package Testing for $TEST_PACKAGE" diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c56fd96814b21..e4dc30f08c53c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -984,7 +984,7 @@ x-pack/solutions/security/packages/kbn-securitysolution-list-hooks @elastic/secu x-pack/solutions/security/packages/kbn-securitysolution-list-utils @elastic/security-detection-engine x-pack/solutions/security/packages/kbn-securitysolution-lists-common @elastic/security-detection-engine x-pack/solutions/security/packages/kbn-securitysolution-t-grid @elastic/security-detection-engine -x-pack/solutions/security/packages/kbn-securitysolution-utils @elastic/security-detection-engine +x-pack/solutions/security/packages/kbn-securitysolution-utils @elastic/security-detection-engine @elastic/security-detection-rule-management x-pack/solutions/security/packages/navigation @elastic/security-threat-hunting-explore x-pack/solutions/security/packages/side_nav @elastic/security-threat-hunting-explore x-pack/solutions/security/packages/storybook/config @elastic/security-threat-hunting-explore @@ -1247,7 +1247,6 @@ packages/kbn-monaco/src/esql @elastic/kibana-esql # Observability UI -/x-pack/test/api_integration/apis/streams @elastic/observability-ui # Assigned per https://github.com/elastic/kibana/pull/201293 /x-pack/test_serverless/api_integration/test_suites/observability/config.ts @elastic/observability-ui @elastic/appex-qa /x-pack/test_serverless/api_integration/test_suites/observability/index.ts @elastic/observability-ui @@ -1450,6 +1449,9 @@ packages/kbn-monaco/src/esql @elastic/kibana-esql # Observability settings /x-pack/plugins/observability_solution/observability/server/ui_settings.ts @elastic/obs-docs +# Streams +/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams @elastic/streams-program-team + ### END Observability Plugins # Presentation @@ -2187,6 +2189,7 @@ x-pack/test/security_solution_api_integration/test_suites/detections_response/te x-pack/test/security_solution_api_integration/test_suites/detections_response/user_roles @elastic/security-detections-response x-pack/test/security_solution_api_integration/test_suites/explore @elastic/security-threat-hunting-explore x-pack/test/security_solution_api_integration/test_suites/investigations @elastic/security-threat-hunting-investigations +x-pack/test/security_solution_api_integration/test_suites/siem_migrations @elastic/security-threat-hunting x-pack/test/security_solution_api_integration/test_suites/sources @elastic/security-detections-response /x-pack/test/common/utils/security_solution/detections_response @elastic/security-detections-response /x-pack/test/functional/es_archives/signals @elastic/security-detections-response @@ -2513,6 +2516,9 @@ x-pack/solutions/security/plugins/security_solution/public/common/components/ses x-pack/solutions/security/plugins/security_solution/public/cloud_defend @elastic/kibana-cloud-security-posture x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture @elastic/kibana-cloud-security-posture x-pack/solutions/security/plugins/security_solution/public/kubernetes @elastic/kibana-cloud-security-posture +x-pack/test/security_solution_api_integration/test_suites/asset_inventory @elastic/kibana-cloud-security-posture +x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory @elastic/kibana-cloud-security-posture + ## Fleet plugin (co-owned with Fleet team) x-pack/platform/plugins/shared/fleet/public/components/cloud_security_posture @elastic/fleet @elastic/kibana-cloud-security-posture x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/components/cloud_security_posture @elastic/fleet @elastic/kibana-cloud-security-posture @@ -2580,6 +2586,9 @@ x-pack/solutions/security/plugins/security_solution/server/lib/security_integrat # Changes to translation files should not ping code reviewers x-pack/platform/plugins/private/translations/translations +# Profiling cypress tests +x-pack/test/profiling_cypress @elastic/obs-ux-infra_services-team + # Profiling api integration testing x-pack/test/profiling_api_integration @elastic/obs-ux-infra_services-team diff --git a/.gitignore b/.gitignore index e59ae47c01cde..a980a79f9fc49 100644 --- a/.gitignore +++ b/.gitignore @@ -137,6 +137,7 @@ src/platform/packages/**/package-map.json /packages/kbn-synthetic-package-map/ **/.synthetics/ **/.journeys/ +**/.rca/ x-pack/test/security_api_integration/plugins/audit_log/audit.log # ignore FTR temp directory diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 186c344afca66..a63e3c5518651 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: 2025-01-16 +date: 2025-01-21 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 e0949783ea2eb..f40ab8f1948cf 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: 2025-01-16 +date: 2025-01-21 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 90b02966d152d..ed128e4f76c10 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: 2025-01-16 +date: 2025-01-21 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 d2972fe38895c..934b76656ce25 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.devdocs.json b/api_docs/alerting.devdocs.json index c680add486a53..ee843ec440fdc 100644 --- a/api_docs/alerting.devdocs.json +++ b/api_docs/alerting.devdocs.json @@ -4792,7 +4792,31 @@ "UnsnoozeParams", ") => Promise; unmuteAll: (options: { id: string; }) => Promise; muteInstance: (options: Readonly<{} & { alertId: string; alertInstanceId: string; }>) => Promise; unmuteInstance: (options: Readonly<{} & { alertId: string; alertInstanceId: string; }>) => Promise; bulkUntrackAlerts: (options: Readonly<{ indices?: string[] | undefined; ruleTypeIds?: string[] | undefined; alertUuids?: string[] | undefined; query?: any[] | undefined; } & { isUsingQuery: boolean; }>) => Promise; runSoon: (options: { id: string; }) => Promise; listRuleTypes: () => Promise<", "RegistryAlertTypeWithAuth", - "[]>; scheduleBackfill: (params: Readonly<{ end?: string | undefined; } & { start: string; ruleId: string; }>[]) => Promise<(Readonly<{ end?: string | undefined; } & { id: string; spaceId: string; start: string; rule: Readonly<{ apiKeyCreatedByUser?: boolean | null | undefined; } & { params: Record; id: string; consumer: string; name: string; tags: string[]; enabled: boolean; alertTypeId: string; schedule: Readonly<{} & { interval: string; }>; createdBy: string | null; updatedBy: string | null; createdAt: string; updatedAt: string; apiKeyOwner: string | null; revision: number; }>; enabled: boolean; schedule: Readonly<{} & { interval: string; status: \"error\" | \"running\" | \"complete\" | \"pending\" | \"timeout\"; runAt: string; }>[]; createdAt: string; duration: string; status: \"error\" | \"running\" | \"complete\" | \"pending\" | \"timeout\"; }> | Readonly<{} & { error: Readonly<{ status?: number | undefined; } & { message: string; rule: Readonly<{ name?: string | undefined; } & { id: string; }>; }>; }>)[]>; getBackfill: (id: string) => Promise; id: string; consumer: string; name: string; tags: string[]; enabled: boolean; alertTypeId: string; schedule: Readonly<{} & { interval: string; }>; createdBy: string | null; updatedBy: string | null; createdAt: string; updatedAt: string; apiKeyOwner: string | null; revision: number; }>; enabled: boolean; schedule: Readonly<{} & { interval: string; status: \"error\" | \"running\" | \"complete\" | \"pending\" | \"timeout\"; runAt: string; }>[]; createdAt: string; duration: string; status: \"error\" | \"running\" | \"complete\" | \"pending\" | \"timeout\"; }>>; findBackfill: (params: Readonly<{ start?: string | undefined; end?: string | undefined; sortField?: \"start\" | \"createdAt\" | undefined; sortOrder?: \"asc\" | \"desc\" | undefined; ruleIds?: string | undefined; } & { page: number; perPage: number; }>) => Promise; id: string; consumer: string; name: string; tags: string[]; enabled: boolean; alertTypeId: string; schedule: Readonly<{} & { interval: string; }>; createdBy: string | null; updatedBy: string | null; createdAt: string; updatedAt: string; apiKeyOwner: string | null; revision: number; }>; enabled: boolean; schedule: Readonly<{} & { interval: string; status: \"error\" | \"running\" | \"complete\" | \"pending\" | \"timeout\"; runAt: string; }>[]; createdAt: string; duration: string; status: \"error\" | \"running\" | \"complete\" | \"pending\" | \"timeout\"; }>[]; perPage: number; total: number; }>>; deleteBackfill: (id: string) => Promise<{}>; getSpaceId: () => string | undefined; getAuthorization: () => ", + "[]>; scheduleBackfill: (params: Readonly<{ end?: string | undefined; runActions?: boolean | undefined; } & { start: string; ruleId: string; }>[]) => Promise<(Readonly<{ end?: string | undefined; warnings?: string[] | undefined; } & { id: string; spaceId: string; start: string; rule: Readonly<{ apiKeyCreatedByUser?: boolean | null | undefined; } & { params: Record; id: string; consumer: string; name: string; actions: Readonly<{ frequency?: Readonly<{} & { throttle: string | null; notifyWhen: \"onActionGroupChange\" | \"onActiveAlert\" | \"onThrottleInterval\"; summary: boolean; }> | undefined; alertsFilter?: Readonly<{ query?: Readonly<{ dsl?: string | undefined; } & { kql: string; filters: Readonly<{ query?: Record | undefined; $state?: Readonly<{} & { store: ", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.FilterStateStore", + "text": "FilterStateStore" + }, + "; }> | undefined; } & { meta: Record; }>[]; }> | undefined; timeframe?: Readonly<{} & { days: (2 | 1 | 7 | 6 | 5 | 4 | 3)[]; hours: Readonly<{} & { start: string; end: string; }>; timezone: string; }> | undefined; } & {}> | undefined; uuid?: string | undefined; useAlertDataForTemplate?: boolean | undefined; } & { params: Record; id: string; actionTypeId: string; group: string; }>[]; tags: string[]; enabled: boolean; alertTypeId: string; schedule: Readonly<{} & { interval: string; }>; createdBy: string | null; updatedBy: string | null; createdAt: string; updatedAt: string; apiKeyOwner: string | null; revision: number; }>; enabled: boolean; schedule: Readonly<{} & { interval: string; status: \"error\" | \"running\" | \"complete\" | \"pending\" | \"timeout\"; runAt: string; }>[]; createdAt: string; duration: string; status: \"error\" | \"running\" | \"complete\" | \"pending\" | \"timeout\"; }> | Readonly<{} & { error: Readonly<{ status?: number | undefined; } & { message: string; rule: Readonly<{ name?: string | undefined; } & { id: string; }>; }>; }>)[]>; getBackfill: (id: string) => Promise; id: string; consumer: string; name: string; actions: Readonly<{ frequency?: Readonly<{} & { throttle: string | null; notifyWhen: \"onActionGroupChange\" | \"onActiveAlert\" | \"onThrottleInterval\"; summary: boolean; }> | undefined; alertsFilter?: Readonly<{ query?: Readonly<{ dsl?: string | undefined; } & { kql: string; filters: Readonly<{ query?: Record | undefined; $state?: Readonly<{} & { store: ", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.FilterStateStore", + "text": "FilterStateStore" + }, + "; }> | undefined; } & { meta: Record; }>[]; }> | undefined; timeframe?: Readonly<{} & { days: (2 | 1 | 7 | 6 | 5 | 4 | 3)[]; hours: Readonly<{} & { start: string; end: string; }>; timezone: string; }> | undefined; } & {}> | undefined; uuid?: string | undefined; useAlertDataForTemplate?: boolean | undefined; } & { params: Record; id: string; actionTypeId: string; group: string; }>[]; tags: string[]; enabled: boolean; alertTypeId: string; schedule: Readonly<{} & { interval: string; }>; createdBy: string | null; updatedBy: string | null; createdAt: string; updatedAt: string; apiKeyOwner: string | null; revision: number; }>; enabled: boolean; schedule: Readonly<{} & { interval: string; status: \"error\" | \"running\" | \"complete\" | \"pending\" | \"timeout\"; runAt: string; }>[]; createdAt: string; duration: string; status: \"error\" | \"running\" | \"complete\" | \"pending\" | \"timeout\"; }>>; findBackfill: (params: Readonly<{ start?: string | undefined; end?: string | undefined; sortField?: \"start\" | \"createdAt\" | undefined; sortOrder?: \"asc\" | \"desc\" | undefined; ruleIds?: string | undefined; } & { page: number; perPage: number; }>) => Promise; id: string; consumer: string; name: string; actions: Readonly<{ frequency?: Readonly<{} & { throttle: string | null; notifyWhen: \"onActionGroupChange\" | \"onActiveAlert\" | \"onThrottleInterval\"; summary: boolean; }> | undefined; alertsFilter?: Readonly<{ query?: Readonly<{ dsl?: string | undefined; } & { kql: string; filters: Readonly<{ query?: Record | undefined; $state?: Readonly<{} & { store: ", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.FilterStateStore", + "text": "FilterStateStore" + }, + "; }> | undefined; } & { meta: Record; }>[]; }> | undefined; timeframe?: Readonly<{} & { days: (2 | 1 | 7 | 6 | 5 | 4 | 3)[]; hours: Readonly<{} & { start: string; end: string; }>; timezone: string; }> | undefined; } & {}> | undefined; uuid?: string | undefined; useAlertDataForTemplate?: boolean | undefined; } & { params: Record; id: string; actionTypeId: string; group: string; }>[]; tags: string[]; enabled: boolean; alertTypeId: string; schedule: Readonly<{} & { interval: string; }>; createdBy: string | null; updatedBy: string | null; createdAt: string; updatedAt: string; apiKeyOwner: string | null; revision: number; }>; enabled: boolean; schedule: Readonly<{} & { interval: string; status: \"error\" | \"running\" | \"complete\" | \"pending\" | \"timeout\"; runAt: string; }>[]; createdAt: string; duration: string; status: \"error\" | \"running\" | \"complete\" | \"pending\" | \"timeout\"; }>[]; perPage: number; total: number; }>>; deleteBackfill: (id: string) => Promise<{}>; getSpaceId: () => string | undefined; getAuthorization: () => ", { "pluginId": "alerting", "scope": "server", diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index 02c30add591d7..371d320633684 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 95c70b9f30671..edc422bc73925 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: 2025-01-16 +date: 2025-01-21 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 4e26ab0b6f890..88c360797136a 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apmDataAccess'] --- import apmDataAccessObj from './apm_data_access.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index 53b56f528e5a2..f43582f0b3b5a 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] --- import bannersObj from './banners.devdocs.json'; diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index 71c4d9e889fc9..8531eb28fd03d 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.devdocs.json b/api_docs/cases.devdocs.json index ebde3b2df2eeb..f0b4fae171bbb 100644 --- a/api_docs/cases.devdocs.json +++ b/api_docs/cases.devdocs.json @@ -3518,7 +3518,7 @@ "CustomFieldTypes", ".TOGGLE; value: boolean | null; } | { key: string; type: ", "CustomFieldTypes", - ".NUMBER; value: number | null; })[]; }; } | { type: \"comment\"; payload: { comment: { type: ", + ".NUMBER; value: number | null; })[]; }; } | { type: \"comment\"; payload: { comment: { comment: string; type: ", { "pluginId": "cases", "scope": "common", @@ -3526,7 +3526,23 @@ "section": "def-common.AttachmentType", "text": "AttachmentType" }, - ".alert; alertId: string | string[]; index: string | string[]; rule: { id: string | null; name: string | null; }; owner: string; } | { externalReferenceId: string; externalReferenceStorage: { type: ", + ".user; owner: string; } | { type: ", + { + "pluginId": "cases", + "scope": "common", + "docId": "kibCasesPluginApi", + "section": "def-common.AttachmentType", + "text": "AttachmentType" + }, + ".alert; alertId: string | string[]; index: string | string[]; rule: { id: string | null; name: string | null; }; owner: string; } | { type: ", + { + "pluginId": "cases", + "scope": "common", + "docId": "kibCasesPluginApi", + "section": "def-common.AttachmentType", + "text": "AttachmentType" + }, + ".actions; comment: string; actions: { targets: { hostname: string; endpointId: string; }[]; type: string; }; owner: string; } | { externalReferenceId: string; externalReferenceStorage: { type: ", { "pluginId": "cases", "scope": "common", @@ -3590,23 +3606,7 @@ "section": "def-common.JsonValue", "text": "JsonValue" }, - "; }; } | { comment: string; type: ", - { - "pluginId": "cases", - "scope": "common", - "docId": "kibCasesPluginApi", - "section": "def-common.AttachmentType", - "text": "AttachmentType" - }, - ".user; owner: string; } | { type: ", - { - "pluginId": "cases", - "scope": "common", - "docId": "kibCasesPluginApi", - "section": "def-common.AttachmentType", - "text": "AttachmentType" - }, - ".actions; comment: string; actions: { targets: { hostname: string; endpointId: string; }[]; type: string; }; owner: string; }; }; } | ({ type: \"create_case\"; } & { payload: { connector: { id: string; } & (({ type: ", + "; }; }; }; } | ({ type: \"create_case\"; } & { payload: { connector: { id: string; } & (({ type: ", { "pluginId": "cases", "scope": "common", diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index 37f0ae17c4f4d..fe7a83fcfb815 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: 2025-01-16 +date: 2025-01-21 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 570edd0958863..f479ad71ca2a0 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: 2025-01-16 +date: 2025-01-21 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 c5d0a1498e2e7..7fb0528371196 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: 2025-01-16 +date: 2025-01-21 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 a7d74012a9348..b3148d9554a11 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: 2025-01-16 +date: 2025-01-21 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 dd0e22558718e..c575ae1e5c961 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDefend'] --- import cloudDefendObj from './cloud_defend.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index 2a1e2127899a6..8692a797c319f 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: 2025-01-16 +date: 2025-01-21 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 07e8aef2bcefc..0e0b01bdb46f8 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: 2025-01-16 +date: 2025-01-21 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 9b16be764369f..8d233d86f9b57 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'contentManagement'] --- import contentManagementObj from './content_management.devdocs.json'; diff --git a/api_docs/controls.devdocs.json b/api_docs/controls.devdocs.json index 9b1dedbf113ae..9e7dbbac3e8c7 100644 --- a/api_docs/controls.devdocs.json +++ b/api_docs/controls.devdocs.json @@ -1060,7 +1060,7 @@ "signature": [ "\"clearControl\"" ], - "path": "src/platform/plugins/shared/controls/public/actions/index.ts", + "path": "src/platform/plugins/shared/controls/public/actions/constants.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -1075,7 +1075,7 @@ "signature": [ "\"deleteControl\"" ], - "path": "src/platform/plugins/shared/controls/public/actions/index.ts", + "path": "src/platform/plugins/shared/controls/public/actions/constants.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -1090,7 +1090,7 @@ "signature": [ "\"editDataControl\"" ], - "path": "src/platform/plugins/shared/controls/public/actions/index.ts", + "path": "src/platform/plugins/shared/controls/public/actions/constants.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index df70bae818057..490e141998f1c 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: 2025-01-16 +date: 2025-01-21 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 63c58827119a6..5e67f1381d0d2 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: 2025-01-16 +date: 2025-01-21 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 904bfeee2f2b0..054efc9da038f 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: 2025-01-16 +date: 2025-01-21 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 be1f30f5bf181..c5f774fc16158 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: 2025-01-16 +date: 2025-01-21 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 3400f41895daa..42255c0cf3b76 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: 2025-01-16 +date: 2025-01-21 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 d1554570ddfbc..9835a136de6a4 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: 2025-01-16 +date: 2025-01-21 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 1dc0ca1509268..90650fdc5310c 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: 2025-01-16 +date: 2025-01-21 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 c8ee7251ce07f..a75a6cb1a9293 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_usage.mdx b/api_docs/data_usage.mdx index 2aa1670041487..19562998354a1 100644 --- a/api_docs/data_usage.mdx +++ b/api_docs/data_usage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataUsage title: "dataUsage" image: https://source.unsplash.com/400x175/?github description: API docs for the dataUsage plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataUsage'] --- import dataUsageObj from './data_usage.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index ece7921e0286f..883d717a06364 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: 2025-01-16 +date: 2025-01-21 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 108992ed83cfa..1fd01ee63d750 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: 2025-01-16 +date: 2025-01-21 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 8298f2ad3309e..091779ce26db7 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: 2025-01-16 +date: 2025-01-21 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 22c418d92e282..5bb662bfa3b0b 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: 2025-01-16 +date: 2025-01-21 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 103f7418077b1..69cbb4d2e58dc 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: 2025-01-16 +date: 2025-01-21 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 a9aafd8e32271..7165db150b5ed 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: 2025-01-16 +date: 2025-01-21 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 65e5f4ecf85c8..809d47b20bece 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -21,7 +21,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | data, @kbn/search-errors, savedObjectsManagement, unifiedSearch, @kbn/unified-field-list, lens, controls, @kbn/lens-embeddable-utils, triggersActionsUi, dataVisualizer, ml, canvas, graph, fleet, transform, @kbn/ml-data-view-utils, upgradeAssistant, securitySolution, timelines, exploratoryView, stackAlerts, maps, visTypeTimeseries, uptime, ux, enterpriseSearch, @kbn/cloud-security-posture-graph, eventAnnotationListing, inputControlVis, visDefaultEditor, dataViewManagement, visTypeTimelion, visTypeVega | - | | | ml, securitySolution | - | | | actions, ml, savedObjectsTagging | - | -| | unifiedSearch, uiActionsEnhanced, controls, ml, discover, imageEmbeddable, securitySolution, links | - | +| | unifiedSearch, uiActionsEnhanced, ml, discover, imageEmbeddable, securitySolution, links | - | | | data, esql, visualizations, lens, maps, cases, ml, aiops, discover, reporting, discoverEnhanced, dashboardEnhanced, securitySolution, slo, synthetics, inputControlVis | - | | | @kbn/core, usageCollection, taskManager, security, monitoringCollection, files, banners, telemetry, securitySolution, @kbn/test-suites-xpack, cloudFullStory, customBranding, enterpriseSearch, interactiveSetup, mockIdpPlugin, spaces, ml | - | | | @kbn/core, visualizations, dataVisualizer, ml, aiops, graph, dashboardEnhanced, lens, securitySolution, eventAnnotation, @kbn/core-saved-objects-browser-mocks | - | @@ -44,6 +44,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | securitySolution, synthetics, cloudDefend | - | | | securitySolution, synthetics, cloudDefend | - | | | cases, securitySolution, security | - | +| | fleet, datasetQuality, securitySolution, synthetics | - | | | @kbn/securitysolution-data-table, securitySolution | - | | | @kbn/securitysolution-data-table, securitySolution | - | | | securitySolution | - | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 94e562357db1e..ab633571bfeb1 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -474,7 +474,6 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| | | [options_list_fetch_cache.ts](https://github.com/elastic/kibana/tree/main/src/platform/plugins/shared/controls/public/controls/data_controls/options_list_control/options_list_fetch_cache.ts#:~:text=title) | - | -| | [plugin.ts](https://github.com/elastic/kibana/tree/main/src/platform/plugins/shared/controls/public/plugin.ts#:~:text=registerAction), [plugin.ts](https://github.com/elastic/kibana/tree/main/src/platform/plugins/shared/controls/public/plugin.ts#:~:text=registerAction), [plugin.ts](https://github.com/elastic/kibana/tree/main/src/platform/plugins/shared/controls/public/plugin.ts#:~:text=registerAction) | - | | | [control_group_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/platform/plugins/shared/controls/server/control_group/control_group_persistable_state.ts#:~:text=SavedObjectReference), [control_group_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/platform/plugins/shared/controls/server/control_group/control_group_persistable_state.ts#:~:text=SavedObjectReference), [control_group_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/platform/plugins/shared/controls/server/control_group/control_group_persistable_state.ts#:~:text=SavedObjectReference), [options_list_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/platform/plugins/shared/controls/server/options_list/options_list_persistable_state.ts#:~:text=SavedObjectReference), [options_list_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/platform/plugins/shared/controls/server/options_list/options_list_persistable_state.ts#:~:text=SavedObjectReference), [options_list_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/platform/plugins/shared/controls/server/options_list/options_list_persistable_state.ts#:~:text=SavedObjectReference), [range_slider_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/platform/plugins/shared/controls/server/range_slider/range_slider_persistable_state.ts#:~:text=SavedObjectReference), [range_slider_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/platform/plugins/shared/controls/server/range_slider/range_slider_persistable_state.ts#:~:text=SavedObjectReference), [range_slider_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/platform/plugins/shared/controls/server/range_slider/range_slider_persistable_state.ts#:~:text=SavedObjectReference), [time_slider_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/platform/plugins/shared/controls/server/time_slider/time_slider_persistable_state.ts#:~:text=SavedObjectReference)+ 2 more | - | @@ -583,6 +582,14 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] +## datasetQuality + +| Deprecated API | Reference location(s) | Remove By | +| ---------------|-----------|-----------| +| | [data_telemetry_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/dataset_quality/server/services/data_telemetry/data_telemetry_service.ts#:~:text=getIsOptedIn) | - | + + + ## discover | Deprecated API | Reference location(s) | Remove By | @@ -730,6 +737,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [agent_policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/common/services/agent_policy_config.test.ts#:~:text=mode), [agent_policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/common/services/agent_policy_config.test.ts#:~:text=mode), [agent_policy_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_watch.test.ts#:~:text=mode), [agent_policy_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_watch.test.ts#:~:text=mode) | 8.8.0 | | | [transform_api_keys.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/api_keys/transform_api_keys.ts#:~:text=authc), [security.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/api_keys/security.ts#:~:text=authc), [fleet_server_policies_enrollment_keys.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/setup/fleet_server_policies_enrollment_keys.ts#:~:text=authc), [handlers.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/routes/setup/handlers.ts#:~:text=authc), [handlers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/routes/setup/handlers.test.ts#:~:text=authc), [handlers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/routes/setup/handlers.test.ts#:~:text=authc), [handlers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/routes/setup/handlers.test.ts#:~:text=authc), [transform_api_keys.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/api_keys/transform_api_keys.ts#:~:text=authc), [security.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/api_keys/security.ts#:~:text=authc), [fleet_server_policies_enrollment_keys.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/setup/fleet_server_policies_enrollment_keys.ts#:~:text=authc)+ 4 more | - | | | [security.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/security/security.ts#:~:text=get), [security.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/security/security.ts#:~:text=get), [security.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/security/security.ts#:~:text=get), [security.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/security/security.ts#:~:text=get), [security.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/security/security.ts#:~:text=get), [security.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/security/security.ts#:~:text=get), [security.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/security/security.ts#:~:text=get), [security.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/security/security.ts#:~:text=get), [security.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/security/security.ts#:~:text=get), [security.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/security/security.ts#:~:text=get)+ 18 more | - | +| | [sender.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/telemetry/sender.ts#:~:text=getIsOptedIn), [sender.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/telemetry/sender.test.ts#:~:text=getIsOptedIn), [sender.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/telemetry/sender.test.ts#:~:text=getIsOptedIn) | - | | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/public/applications/integrations/index.tsx#:~:text=appBasePath) | - | | | [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion), [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion), [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [install.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.test.ts#:~:text=migrationVersion), [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion), [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion)+ 6 more | - | | | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/saved_objects/index.ts#:~:text=migrations), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/saved_objects/index.ts#:~:text=migrations), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/saved_objects/index.ts#:~:text=migrations), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/saved_objects/index.ts#:~:text=migrations), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/fleet/server/saved_objects/index.ts#:~:text=migrations) | - | @@ -1219,6 +1227,7 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | | [get_is_alert_suppression_active.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_is_alert_suppression_active.ts#:~:text=license%24), [create_threat_signals.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signals.ts#:~:text=license%24), [query.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts#:~:text=license%24), [threshold.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/threshold.ts#:~:text=license%24), [get_is_alert_suppression_active.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_is_alert_suppression_active.test.ts#:~:text=license%24), [get_is_alert_suppression_active.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_is_alert_suppression_active.test.ts#:~:text=license%24), [get_is_alert_suppression_active.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_is_alert_suppression_active.test.ts#:~:text=license%24) | 8.8.0 | | | [route.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/route.ts#:~:text=authc) | - | | | [suggest_user_profiles_route.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/routes/users/suggest_user_profiles_route.ts#:~:text=userProfiles), [get_notes.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/notes/get_notes.ts#:~:text=userProfiles), [suggest_user_profiles_route.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/routes/users/suggest_user_profiles_route.ts#:~:text=userProfiles), [get_notes.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/notes/get_notes.ts#:~:text=userProfiles) | - | +| | [sender.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/lib/telemetry/sender.ts#:~:text=getIsOptedIn), [sender_helpers.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/lib/telemetry/sender_helpers.ts#:~:text=getIsOptedIn), [sender.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/lib/telemetry/sender.test.ts#:~:text=getIsOptedIn) | - | | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/public/common/components/events_viewer/index.tsx#:~:text=DeprecatedCellValueElementProps), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/public/common/components/events_viewer/index.tsx#:~:text=DeprecatedCellValueElementProps) | - | | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/public/common/components/events_viewer/index.tsx#:~:text=DeprecatedRowRenderer), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/public/common/components/events_viewer/index.tsx#:~:text=DeprecatedRowRenderer) | - | | | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/common/search_strategy/index_fields/index.ts#:~:text=BeatFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=BeatFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=BeatFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=BeatFields) | - | @@ -1249,7 +1258,7 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | | [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/public/management/pages/blocklist/constants.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_NAME), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/public/management/pages/blocklist/constants.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_NAME), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/blocklists/index.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_NAME), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/blocklists/index.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_NAME) | - | | | [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/public/management/pages/blocklist/constants.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_DESCRIPTION), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/public/management/pages/blocklist/constants.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_DESCRIPTION), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/blocklists/index.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_DESCRIPTION), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/blocklists/index.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_DESCRIPTION) | - | | | [use_colors.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/public/resolver/view/use_colors.ts#:~:text=darkMode), [use_colors.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/public/resolver/view/use_colors.ts#:~:text=darkMode), [use_colors.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/public/resolver/view/use_colors.ts#:~:text=darkMode), [use_colors.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/public/resolver/view/use_colors.ts#:~:text=darkMode), [use_colors.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/public/resolver/view/use_colors.ts#:~:text=darkMode) | - | -| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.tsx#:~:text=externalControlColumns) | - | +| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.tsx#:~:text=externalControlColumns), [all_assets.tsx](https://github.com/elastic/kibana/tree/main/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/pages/all_assets.tsx#:~:text=externalControlColumns) | - | @@ -1292,7 +1301,7 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [on_post_auth_interceptor.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/spaces/server/lib/request_interceptors/on_post_auth_interceptor.ts#:~:text=getKibanaFeatures), [spaces_usage_collector.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/spaces/server/usage_collection/spaces_usage_collector.ts#:~:text=getKibanaFeatures), [on_post_auth_interceptor.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts#:~:text=getKibanaFeatures) | 8.8.0 | +| | [spaces_usage_collector.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/spaces/server/usage_collection/spaces_usage_collector.ts#:~:text=getKibanaFeatures) | 8.8.0 | | | [spaces_usage_collector.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/spaces/server/usage_collection/spaces_usage_collector.ts#:~:text=license%24), [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/spaces/server/plugin.ts#:~:text=license%24), [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/spaces/server/plugin.ts#:~:text=license%24), [spaces_usage_collector.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/spaces/server/usage_collection/spaces_usage_collector.test.ts#:~:text=license%24) | 8.8.0 | | | [capabilities_switcher.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/spaces/server/capabilities/capabilities_switcher.ts#:~:text=authRequired) | - | | | [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/spaces/public/legacy_urls/types.ts#:~:text=ResolvedSimpleSavedObject), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/spaces/public/legacy_urls/types.ts#:~:text=ResolvedSimpleSavedObject) | - | @@ -1339,6 +1348,7 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | | [synthetics_private_location.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/private_location/synthetics_private_location.ts#:~:text=policy_id) | - | | | [synthetics_private_location.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/private_location/synthetics_private_location.ts#:~:text=policy_id) | - | | | [get_api_key.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/get_api_key.ts#:~:text=authc), [get_api_key.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/get_api_key.ts#:~:text=authc), [get_api_key.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/get_api_key.ts#:~:text=authc), [get_api_key.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/get_api_key.ts#:~:text=authc), [get_api_key.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/get_api_key.ts#:~:text=authc), [get_api_key.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/get_api_key.ts#:~:text=authc), [enablement.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/server/routes/synthetics_service/enablement.ts#:~:text=authc), [enablement.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/server/routes/synthetics_service/enablement.ts#:~:text=authc), [get_api_key.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/get_api_key.ts#:~:text=authc), [get_api_key.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/get_api_key.ts#:~:text=authc)+ 6 more | - | +| | [sender.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/server/telemetry/sender.ts#:~:text=getIsOptedIn), [sender.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/server/telemetry/sender.test.ts#:~:text=getIsOptedIn), [sender.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/server/telemetry/sender.test.ts#:~:text=getIsOptedIn) | - | | | [register_ui_actions.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/public/apps/embeddables/ui_actions/register_ui_actions.ts#:~:text=addTriggerAction), [register_ui_actions.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/public/apps/embeddables/ui_actions/register_ui_actions.ts#:~:text=addTriggerAction) | - | | | [synthetics_monitor.ts](https://github.com/elastic/kibana/tree/main/x-pack/solutions/observability/plugins/synthetics/server/saved_objects/synthetics_monitor.ts#:~:text=migrations) | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 9ba2dbf8aec27..e89f9022e17f6 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -66,7 +66,7 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ This is relied on by the reporting feature, and should be removed once reporting migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/issues/19914 | -| security | | [app_authorization.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/security/server/authorization/app_authorization.ts#:~:text=getKibanaFeatures), [authorization_service.tsx](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/security/server/authorization/authorization_service.tsx#:~:text=getKibanaFeatures), [app_authorization.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/security/server/authorization/app_authorization.test.ts#:~:text=getKibanaFeatures), [on_post_auth_interceptor.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/spaces/server/lib/request_interceptors/on_post_auth_interceptor.ts#:~:text=getKibanaFeatures), [spaces_usage_collector.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/spaces/server/usage_collection/spaces_usage_collector.ts#:~:text=getKibanaFeatures), [on_post_auth_interceptor.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts#:~:text=getKibanaFeatures), [privileges.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/packages/private/security/authorization_core/src/privileges/privileges.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/packages/private/security/authorization_core/src/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/packages/private/security/authorization_core/src/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/packages/private/security/authorization_core/src/privileges/privileges.test.ts#:~:text=getKibanaFeatures)+ 30 more | 8.8.0 | +| security | | [app_authorization.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/security/server/authorization/app_authorization.ts#:~:text=getKibanaFeatures), [authorization_service.tsx](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/security/server/authorization/authorization_service.tsx#:~:text=getKibanaFeatures), [app_authorization.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/security/server/authorization/app_authorization.test.ts#:~:text=getKibanaFeatures), [spaces_usage_collector.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/spaces/server/usage_collection/spaces_usage_collector.ts#:~:text=getKibanaFeatures), [privileges.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/packages/private/security/authorization_core/src/privileges/privileges.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/packages/private/security/authorization_core/src/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/packages/private/security/authorization_core/src/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/packages/private/security/authorization_core/src/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/packages/private/security/authorization_core/src/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/packages/private/security/authorization_core/src/privileges/privileges.test.ts#:~:text=getKibanaFeatures)+ 28 more | 8.8.0 | | security | | [authorization_service.tsx](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/security/server/authorization/authorization_service.tsx#:~:text=getElasticsearchFeatures), [kibana_privileges.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/packages/private/security/role_management_model/src/__fixtures__/kibana_privileges.ts#:~:text=getElasticsearchFeatures) | 8.8.0 | | security | | [license_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/security/common/licensing/license_service.test.ts#:~:text=mode), [license_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/security/common/licensing/license_service.test.ts#:~:text=mode), [license_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/security/common/licensing/license_service.test.ts#:~:text=mode) | 8.8.0 | | security | | [plugin.tsx](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/security/public/plugin.tsx#:~:text=license%24) | 8.8.0 | diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 41a55110aca04..262948d8ecfe4 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: 2025-01-16 +date: 2025-01-21 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 1dfd0a73ee7ae..3e997954742b4 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: 2025-01-16 +date: 2025-01-21 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 60d4263a275ef..2acdce52a8a9c 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: 2025-01-16 +date: 2025-01-21 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 23865abb90dfb..5d94dfaf57bdc 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: 2025-01-16 +date: 2025-01-21 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 3827c9e22f4b3..bd4a53d48ead8 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/elastic_assistant.mdx b/api_docs/elastic_assistant.mdx index 9a116e0a5a6b4..65b5151459479 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'elasticAssistant'] --- import elasticAssistantObj from './elastic_assistant.devdocs.json'; diff --git a/api_docs/embeddable.devdocs.json b/api_docs/embeddable.devdocs.json index ba3a7e414ba4b..6d1a861ac88c9 100644 --- a/api_docs/embeddable.devdocs.json +++ b/api_docs/embeddable.devdocs.json @@ -1906,21 +1906,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "embeddable", - "id": "def-public.PANEL_HOVER_TRIGGER", - "type": "string", - "tags": [], - "label": "PANEL_HOVER_TRIGGER", - "description": [], - "signature": [ - "\"PANEL_HOVER_TRIGGER\"" - ], - "path": "src/platform/plugins/shared/embeddable/public/ui_actions/triggers.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "embeddable", "id": "def-public.PANEL_NOTIFICATION_TRIGGER", @@ -2343,53 +2328,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "embeddable", - "id": "def-public.panelHoverTrigger", - "type": "Object", - "tags": [], - "label": "panelHoverTrigger", - "description": [], - "path": "src/platform/plugins/shared/embeddable/public/ui_actions/triggers.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "embeddable", - "id": "def-public.panelHoverTrigger.id", - "type": "string", - "tags": [], - "label": "id", - "description": [], - "path": "src/platform/plugins/shared/embeddable/public/ui_actions/triggers.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "embeddable", - "id": "def-public.panelHoverTrigger.title", - "type": "string", - "tags": [], - "label": "title", - "description": [], - "path": "src/platform/plugins/shared/embeddable/public/ui_actions/triggers.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "embeddable", - "id": "def-public.panelHoverTrigger.description", - "type": "string", - "tags": [], - "label": "description", - "description": [], - "path": "src/platform/plugins/shared/embeddable/public/ui_actions/triggers.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "embeddable", "id": "def-public.panelNotificationTrigger", diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index cca8f45290038..ceb1cd0e6dd17 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kib | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 172 | 0 | 145 | 2 | +| 167 | 0 | 140 | 2 | ## Client diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index 9970eb94b0c7b..51547c793653c 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: 2025-01-16 +date: 2025-01-21 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 74a1dfcc37185..9ec41f875bc20 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: 2025-01-16 +date: 2025-01-21 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 52c8e03529357..919b1b22586f5 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/entities_data_access.mdx b/api_docs/entities_data_access.mdx index 6f496f80d63d8..ef0d3a4ebc782 100644 --- a/api_docs/entities_data_access.mdx +++ b/api_docs/entities_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/entitiesDataAccess title: "entitiesDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the entitiesDataAccess plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'entitiesDataAccess'] --- import entitiesDataAccessObj from './entities_data_access.devdocs.json'; diff --git a/api_docs/entity_manager.mdx b/api_docs/entity_manager.mdx index f1d5f8b64e661..5838f72b9b2cd 100644 --- a/api_docs/entity_manager.mdx +++ b/api_docs/entity_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/entityManager title: "entityManager" image: https://source.unsplash.com/400x175/?github description: API docs for the entityManager plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'entityManager'] --- import entityManagerObj from './entity_manager.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index d906bf2a739ed..7d473f0b1b2d3 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/esql.mdx b/api_docs/esql.mdx index 50a17dc827d13..908eeea1ef0f1 100644 --- a/api_docs/esql.mdx +++ b/api_docs/esql.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esql title: "esql" image: https://source.unsplash.com/400x175/?github description: API docs for the esql plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esql'] --- import esqlObj from './esql.devdocs.json'; diff --git a/api_docs/esql_data_grid.mdx b/api_docs/esql_data_grid.mdx index 9aa48ffc3a3e5..1c1df0cc7a526 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: 2025-01-16 +date: 2025-01-21 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 168b8dc681474..ef98aedab868f 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: 2025-01-16 +date: 2025-01-21 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 6cad23cbe526a..277fa3704a039 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: 2025-01-16 +date: 2025-01-21 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 c8f6c868c2522..45f39ac185ee7 100644 --- a/api_docs/event_log.devdocs.json +++ b/api_docs/event_log.devdocs.json @@ -1514,7 +1514,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; version?: string | undefined; name?: string | undefined; license?: string | undefined; description?: string | undefined; uuid?: string | undefined; category?: 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; type_id?: 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; usage?: Readonly<{ request_body_bytes?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; version?: string | 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; flapping?: boolean | undefined; uuid?: string | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; space_ids?: 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; user_api_key?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | 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; code?: string | undefined; severity?: string | number | undefined; category?: string[] | undefined; timezone?: string | undefined; risk_score?: number | undefined; url?: string | undefined; created?: string | undefined; provider?: string | undefined; dataset?: 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)[]" + "(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; version?: string | undefined; name?: string | undefined; license?: string | undefined; description?: string | undefined; uuid?: string | undefined; category?: 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; type_id?: 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; usage?: Readonly<{ request_body_bytes?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ outcome?: 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; status?: string | 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; flapping?: boolean | undefined; uuid?: string | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; space_ids?: 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; user_api_key?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | 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; timezone?: string | undefined; code?: string | undefined; severity?: string | number | undefined; category?: string[] | undefined; risk_score?: number | undefined; url?: string | undefined; created?: string | undefined; provider?: string | undefined; dataset?: 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/platform/plugins/shared/event_log/server/es/cluster_client_adapter.ts", "deprecated": false, @@ -1534,7 +1534,7 @@ "label": "IEvent", "description": [], "signature": [ - "DeepPartial | 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; version?: string | undefined; name?: string | undefined; license?: string | undefined; description?: string | undefined; uuid?: string | undefined; category?: 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; type_id?: 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; usage?: Readonly<{ request_body_bytes?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; version?: string | 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; flapping?: boolean | undefined; uuid?: string | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; space_ids?: 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; user_api_key?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | 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; code?: string | undefined; severity?: string | number | undefined; category?: string[] | undefined; timezone?: string | undefined; risk_score?: number | undefined; url?: string | undefined; created?: string | undefined; provider?: string | undefined; dataset?: 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" + "DeepPartial | 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; version?: string | undefined; name?: string | undefined; license?: string | undefined; description?: string | undefined; uuid?: string | undefined; category?: 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; type_id?: 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; usage?: Readonly<{ request_body_bytes?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ outcome?: 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; status?: string | 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; flapping?: boolean | undefined; uuid?: string | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; space_ids?: 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; user_api_key?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | 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; timezone?: string | undefined; code?: string | undefined; severity?: string | number | undefined; category?: string[] | undefined; risk_score?: number | undefined; url?: string | undefined; created?: string | undefined; provider?: string | undefined; dataset?: 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/platform/plugins/shared/event_log/generated/schemas.ts", "deprecated": false, @@ -1549,7 +1549,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; version?: string | undefined; name?: string | undefined; license?: string | undefined; description?: string | undefined; uuid?: string | undefined; category?: 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; type_id?: 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; usage?: Readonly<{ request_body_bytes?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; version?: string | 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; flapping?: boolean | undefined; uuid?: string | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; space_ids?: 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; user_api_key?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | 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; code?: string | undefined; severity?: string | number | undefined; category?: string[] | undefined; timezone?: string | undefined; risk_score?: number | undefined; url?: string | undefined; created?: string | undefined; provider?: string | undefined; dataset?: 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" + "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; version?: string | undefined; name?: string | undefined; license?: string | undefined; description?: string | undefined; uuid?: string | undefined; category?: 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; type_id?: 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; usage?: Readonly<{ request_body_bytes?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ outcome?: 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; status?: string | 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; flapping?: boolean | undefined; uuid?: string | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; space_ids?: 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; user_api_key?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | 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; timezone?: string | undefined; code?: string | undefined; severity?: string | number | undefined; category?: string[] | undefined; risk_score?: number | undefined; url?: string | undefined; created?: string | undefined; provider?: string | undefined; dataset?: 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/platform/plugins/shared/event_log/generated/schemas.ts", "deprecated": false, diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index 99fc2b19cc83d..4ca98fe9775d8 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: 2025-01-16 +date: 2025-01-21 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 109d194f4f6a5..eaa5226366067 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: 2025-01-16 +date: 2025-01-21 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 aa56d807e9313..e2a1f47fe1c45 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: 2025-01-16 +date: 2025-01-21 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 d7960a0e63daa..c0da9669e7824 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.devdocs.json b/api_docs/expression_heatmap.devdocs.json index a110a3e8bef3a..345ec0f9aa2e3 100644 --- a/api_docs/expression_heatmap.devdocs.json +++ b/api_docs/expression_heatmap.devdocs.json @@ -1353,6 +1353,44 @@ } ] }, + { + "parentPluginId": "expressionHeatmap", + "id": "def-common.heatmapGridConfig.args.xAxisLabelRotation", + "type": "Object", + "tags": [], + "label": "xAxisLabelRotation", + "description": [], + "path": "src/platform/plugins/shared/chart_expressions/expression_heatmap/common/expression_functions/heatmap_grid.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "expressionHeatmap", + "id": "def-common.heatmapGridConfig.args.xAxisLabelRotation.types", + "type": "Array", + "tags": [], + "label": "types", + "description": [], + "signature": [ + "\"number\"[]" + ], + "path": "src/platform/plugins/shared/chart_expressions/expression_heatmap/common/expression_functions/heatmap_grid.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "expressionHeatmap", + "id": "def-common.heatmapGridConfig.args.xAxisLabelRotation.help", + "type": "string", + "tags": [], + "label": "help", + "description": [], + "path": "src/platform/plugins/shared/chart_expressions/expression_heatmap/common/expression_functions/heatmap_grid.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, { "parentPluginId": "expressionHeatmap", "id": "def-common.heatmapGridConfig.args.isXAxisTitleVisible", @@ -1455,7 +1493,7 @@ "signature": [ "(input: null, args: ", "HeatmapGridConfig", - ") => { strokeWidth?: number | undefined; strokeColor?: string | undefined; isCellLabelVisible: boolean; isYAxisLabelVisible: boolean; isYAxisTitleVisible: boolean; yTitle?: string | undefined; isXAxisLabelVisible: boolean; isXAxisTitleVisible: boolean; xTitle?: string | undefined; type: \"heatmap_grid\"; }" + ") => { strokeWidth?: number | undefined; strokeColor?: string | undefined; isCellLabelVisible: boolean; isYAxisLabelVisible: boolean; isYAxisTitleVisible: boolean; yTitle?: string | undefined; isXAxisLabelVisible: boolean; xAxisLabelRotation?: number | undefined; isXAxisTitleVisible: boolean; xTitle?: string | undefined; type: \"heatmap_grid\"; }" ], "path": "src/platform/plugins/shared/chart_expressions/expression_heatmap/common/expression_functions/heatmap_grid.ts", "deprecated": false, diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index d7111462333c6..b128637eb24b3 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 112 | 0 | 108 | 2 | +| 115 | 0 | 111 | 2 | ## Common diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index 4876332483d36..3fcdfe5dda561 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: 2025-01-16 +date: 2025-01-21 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 e077fdcd7ef5a..9a36105d63b03 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: 2025-01-16 +date: 2025-01-21 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 1f650143426ec..41a2501798eb9 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: 2025-01-16 +date: 2025-01-21 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 e374b54582eb1..0c99cdefbeff6 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: 2025-01-16 +date: 2025-01-21 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 e81662b009f12..8bad663253b2a 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: 2025-01-16 +date: 2025-01-21 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 f13ca2e9bcdf6..68a960bd019e3 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: 2025-01-16 +date: 2025-01-21 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 8d6bca600d8dc..bc7a5d0bbf2db 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: 2025-01-16 +date: 2025-01-21 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 e90a3f6e03a71..b92b6cd6610b3 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: 2025-01-16 +date: 2025-01-21 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 3e310a1b4fce2..c5d5155deadc0 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: 2025-01-16 +date: 2025-01-21 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 01343ebd92a62..88762f75c4905 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: 2025-01-16 +date: 2025-01-21 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 fb9843869f10d..0131a377ee5f6 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.devdocs.json b/api_docs/features.devdocs.json index 37a21e4a533ce..5fadfe4afec88 100644 --- a/api_docs/features.devdocs.json +++ b/api_docs/features.devdocs.json @@ -72,7 +72,7 @@ "section": "def-common.KibanaFeatureScope", "text": "KibanaFeatureScope" }, - "[] | undefined; readonly deprecated?: Readonly<{ readonly notice: string; }> | undefined; }>" + "[] | undefined; readonly deprecated?: Readonly<{ readonly notice: string; readonly replacedBy?: readonly string[] | undefined; }> | undefined; }>" ], "path": "x-pack/platform/plugins/shared/features/common/kibana_feature.ts", "deprecated": false, @@ -101,7 +101,7 @@ "label": "deprecated", "description": [], "signature": [ - "Readonly<{ readonly notice: string; }> | undefined" + "Readonly<{ readonly notice: string; readonly replacedBy?: readonly string[] | undefined; }> | undefined" ], "path": "x-pack/platform/plugins/shared/features/common/kibana_feature.ts", "deprecated": false, @@ -958,7 +958,7 @@ "\nIf defined, the feature is considered deprecated and won't be available to users when configuring roles or Spaces." ], "signature": [ - "Readonly<{ notice: string; }> | undefined" + "Readonly<{ notice: string; replacedBy?: readonly string[] | undefined; }> | undefined" ], "path": "x-pack/platform/plugins/shared/features/common/kibana_feature.ts", "deprecated": false, @@ -1500,7 +1500,7 @@ "section": "def-common.KibanaFeatureScope", "text": "KibanaFeatureScope" }, - "[] | undefined; readonly deprecated?: Readonly<{ readonly notice: string; }> | undefined; }>" + "[] | undefined; readonly deprecated?: Readonly<{ readonly notice: string; readonly replacedBy?: readonly string[] | undefined; }> | undefined; }>" ], "path": "x-pack/platform/plugins/shared/features/common/kibana_feature.ts", "deprecated": false, @@ -1529,7 +1529,7 @@ "label": "deprecated", "description": [], "signature": [ - "Readonly<{ readonly notice: string; }> | undefined" + "Readonly<{ readonly notice: string; readonly replacedBy?: readonly string[] | undefined; }> | undefined" ], "path": "x-pack/platform/plugins/shared/features/common/kibana_feature.ts", "deprecated": false, @@ -2353,10 +2353,6 @@ "removeBy": "8.8.0", "trackAdoption": false, "references": [ - { - "plugin": "spaces", - "path": "x-pack/platform/plugins/shared/spaces/server/lib/request_interceptors/on_post_auth_interceptor.ts" - }, { "plugin": "spaces", "path": "x-pack/platform/plugins/shared/spaces/server/usage_collection/spaces_usage_collector.ts" @@ -2516,10 +2512,6 @@ { "plugin": "@kbn/security-authorization-core", "path": "x-pack/platform/packages/private/security/authorization_core/src/privileges/privileges.test.ts" - }, - { - "plugin": "spaces", - "path": "x-pack/platform/plugins/shared/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts" } ], "children": [], @@ -2783,9 +2775,19 @@ "type": "Function", "tags": [], "label": "getKibanaFeatures", - "description": [], + "description": [ + "\nReturns all registered Kibana features." + ], "signature": [ - "() => ", + "(params?: ", + { + "pluginId": "features", + "scope": "server", + "docId": "kibFeaturesPluginApi", + "section": "def-server.GetKibanaFeaturesParams", + "text": "GetKibanaFeaturesParams" + }, + " | undefined) => ", { "pluginId": "features", "scope": "common", @@ -2798,12 +2800,66 @@ "path": "x-pack/platform/plugins/shared/features/server/plugin.ts", "deprecated": false, "trackAdoption": false, - "children": [], + "children": [ + { + "parentPluginId": "features", + "id": "def-server.FeaturesPluginStart.getKibanaFeatures.$1", + "type": "Object", + "tags": [], + "label": "params", + "description": [ + "Optional parameters to filter features." + ], + "signature": [ + { + "pluginId": "features", + "scope": "server", + "docId": "kibFeaturesPluginApi", + "section": "def-server.GetKibanaFeaturesParams", + "text": "GetKibanaFeaturesParams" + }, + " | undefined" + ], + "path": "x-pack/platform/plugins/shared/features/server/plugin.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], "returnComment": [] } ], "initialIsOpen": false }, + { + "parentPluginId": "features", + "id": "def-server.GetKibanaFeaturesParams", + "type": "Interface", + "tags": [], + "label": "GetKibanaFeaturesParams", + "description": [ + "\nDescribes parameters used to retrieve all Kibana features (for public consumers)." + ], + "path": "x-pack/platform/plugins/shared/features/server/feature_registry.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "features", + "id": "def-server.GetKibanaFeaturesParams.omitDeprecated", + "type": "boolean", + "tags": [], + "label": "omitDeprecated", + "description": [ + "\nIf true, deprecated features will be omitted. For backward compatibility reasons, deprecated features are included\nin the result by default." + ], + "path": "x-pack/platform/plugins/shared/features/server/feature_registry.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "features", "id": "def-server.KibanaFeatureConfig", @@ -3148,7 +3204,7 @@ "\nIf defined, the feature is considered deprecated and won't be available to users when configuring roles or Spaces." ], "signature": [ - "Readonly<{ notice: string; }> | undefined" + "Readonly<{ notice: string; replacedBy?: readonly string[] | undefined; }> | undefined" ], "path": "x-pack/platform/plugins/shared/features/common/kibana_feature.ts", "deprecated": false, @@ -3524,7 +3580,7 @@ "section": "def-common.KibanaFeatureScope", "text": "KibanaFeatureScope" }, - "[] | undefined; readonly deprecated?: Readonly<{ readonly notice: string; }> | undefined; }>" + "[] | undefined; readonly deprecated?: Readonly<{ readonly notice: string; readonly replacedBy?: readonly string[] | undefined; }> | undefined; }>" ], "path": "x-pack/platform/plugins/shared/features/common/kibana_feature.ts", "deprecated": false, @@ -3553,7 +3609,7 @@ "label": "deprecated", "description": [], "signature": [ - "Readonly<{ readonly notice: string; }> | undefined" + "Readonly<{ readonly notice: string; readonly replacedBy?: readonly string[] | undefined; }> | undefined" ], "path": "x-pack/platform/plugins/shared/features/common/kibana_feature.ts", "deprecated": false, @@ -4767,7 +4823,7 @@ "\nIf defined, the feature is considered deprecated and won't be available to users when configuring roles or Spaces." ], "signature": [ - "Readonly<{ notice: string; }> | undefined" + "Readonly<{ notice: string; replacedBy?: readonly string[] | undefined; }> | undefined" ], "path": "x-pack/platform/plugins/shared/features/common/kibana_feature.ts", "deprecated": false, diff --git a/api_docs/features.mdx b/api_docs/features.mdx index b2c312da2d2fb..ae2c981173fe1 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 270 | 0 | 110 | 3 | +| 273 | 0 | 109 | 3 | ## Client diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index f522ce60a18ec..9783c28c08eb4 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: 2025-01-16 +date: 2025-01-21 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 effbffa997e0c..0b84524b5346e 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: 2025-01-16 +date: 2025-01-21 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 24e6761a6d9cb..ab3d6f4fc34b8 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: 2025-01-16 +date: 2025-01-21 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 57d27430dd605..1c0ba92614732 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: 2025-01-16 +date: 2025-01-21 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 b62f7d8b7c54b..d139bf67d9254 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index 69b7bdf50042f..d5bbab3d26c13 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -26161,6 +26161,21 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "fleet", + "id": "def-common.NewAgentPolicy.agentless", + "type": "Object", + "tags": [], + "label": "agentless", + "description": [], + "signature": [ + "AgentlessPolicy", + " | undefined" + ], + "path": "x-pack/platform/plugins/shared/fleet/common/types/models/agent_policy.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "fleet", "id": "def-common.NewAgentPolicy.monitoring_pprof_enabled", @@ -26202,6 +26217,21 @@ "path": "x-pack/platform/plugins/shared/fleet/common/types/models/agent_policy.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "fleet", + "id": "def-common.NewAgentPolicy.required_versions", + "type": "CompoundType", + "tags": [], + "label": "required_versions", + "description": [], + "signature": [ + "AgentTargetVersion", + "[] | null | undefined" + ], + "path": "x-pack/platform/plugins/shared/fleet/common/types/models/agent_policy.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 9826178066ce4..61cfef1885775 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) for questi | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 1446 | 5 | 1319 | 82 | +| 1448 | 5 | 1321 | 84 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 05478aa3dffdc..75315fc87a789 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: 2025-01-16 +date: 2025-01-21 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 d023848b68221..c5654002e12ad 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: 2025-01-16 +date: 2025-01-21 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 f526312ba6c4b..7eb197ac99b0e 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: 2025-01-16 +date: 2025-01-21 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 2cd51815cefbb..815dd0d82aabb 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'imageEmbeddable'] --- import imageEmbeddableObj from './image_embeddable.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index 1a4a042d7da8e..5d58598b3bb97 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/inference.devdocs.json b/api_docs/inference.devdocs.json index 9bcb1a70a1dec..1716fd4a0d903 100644 --- a/api_docs/inference.devdocs.json +++ b/api_docs/inference.devdocs.json @@ -117,7 +117,7 @@ "section": "def-common.Message", "text": "Message" }, - "[]; temperature?: number | undefined; functionCalling?: ", + "[]; temperature?: number | undefined; modelName?: string | undefined; functionCalling?: ", { "pluginId": "@kbn/inference-common", "scope": "common", @@ -335,7 +335,7 @@ "label": "options", "description": [], "signature": [ - "{ [P in \"abortSignal\" | \"temperature\" | \"system\" | \"stream\" | \"messages\" | Exclude]: ", + "{ [P in \"abortSignal\" | \"temperature\" | \"system\" | \"stream\" | \"messages\" | \"modelName\" | Exclude]: ", { "pluginId": "@kbn/inference-common", "scope": "common", @@ -396,7 +396,7 @@ "label": "options", "description": [], "signature": [ - "{ id: TId; abortSignal?: AbortSignal | undefined; input: string; schema?: TOutputSchema | undefined; retry?: { onValidationError?: number | boolean | undefined; } | undefined; system?: string | undefined; stream?: TStream | undefined; previousMessages?: ", + "{ id: TId; abortSignal?: AbortSignal | undefined; input: string; schema?: TOutputSchema | undefined; retry?: { onValidationError?: number | boolean | undefined; } | undefined; system?: string | undefined; stream?: TStream | undefined; modelName?: string | undefined; previousMessages?: ", { "pluginId": "@kbn/inference-common", "scope": "common", @@ -535,7 +535,7 @@ "section": "def-common.Message", "text": "Message" }, - "[]; temperature?: number | undefined; functionCalling?: ", + "[]; temperature?: number | undefined; modelName?: string | undefined; functionCalling?: ", { "pluginId": "@kbn/inference-common", "scope": "common", @@ -855,7 +855,7 @@ "section": "def-common.ChatCompleteAPI", "text": "ChatCompleteAPI" }, - ") => ({ id, connectorId, input, schema, system, previousMessages, functionCalling, stream, abortSignal, retry, }: DefaultOutputOptions) => Promise<", + ") => ({ id, connectorId, input, schema, system, previousMessages, modelName, functionCalling, stream, abortSignal, retry, }: DefaultOutputOptions) => Promise<", { "pluginId": "@kbn/inference-common", "scope": "common", @@ -1006,7 +1006,7 @@ "label": "ChatCompleteRequestBody", "description": [], "signature": [ - "{ connectorId: string; stream?: boolean | undefined; system?: string | undefined; temperature?: number | undefined; messages: ", + "{ connectorId: string; stream?: boolean | undefined; system?: string | undefined; temperature?: number | undefined; modelName?: string | undefined; messages: ", { "pluginId": "@kbn/inference-common", "scope": "common", diff --git a/api_docs/inference.mdx b/api_docs/inference.mdx index 7650687d78fb2..23f4c1b1b67b9 100644 --- a/api_docs/inference.mdx +++ b/api_docs/inference.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inference title: "inference" image: https://source.unsplash.com/400x175/?github description: API docs for the inference plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inference'] --- import inferenceObj from './inference.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 1d3c3a777eb65..28a606d90f424 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: 2025-01-16 +date: 2025-01-21 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 a65d44f367fe6..488029a927082 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: 2025-01-16 +date: 2025-01-21 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 762f665fd3cce..8c8b6acc0265f 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: 2025-01-16 +date: 2025-01-21 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 d67050c4eaa55..45ca25f22b2a8 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: 2025-01-16 +date: 2025-01-21 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 013278c1ece3e..d3841a4c8a0d4 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/inventory.mdx b/api_docs/inventory.mdx index cc9f4b411c250..aae4ea7a6dc75 100644 --- a/api_docs/inventory.mdx +++ b/api_docs/inventory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inventory title: "inventory" image: https://source.unsplash.com/400x175/?github description: API docs for the inventory plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inventory'] --- import inventoryObj from './inventory.devdocs.json'; diff --git a/api_docs/investigate.mdx b/api_docs/investigate.mdx index 4774a3f4667a9..dd20ac692ed6d 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'investigate'] --- import investigateObj from './investigate.devdocs.json'; diff --git a/api_docs/investigate_app.mdx b/api_docs/investigate_app.mdx index 3cc8c6224a3f8..fc4bbdc6b4a47 100644 --- a/api_docs/investigate_app.mdx +++ b/api_docs/investigate_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/investigateApp title: "investigateApp" image: https://source.unsplash.com/400x175/?github description: API docs for the investigateApp plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'investigateApp'] --- import investigateAppObj from './investigate_app.devdocs.json'; diff --git a/api_docs/kbn_actions_types.mdx b/api_docs/kbn_actions_types.mdx index da9d0494ea9ea..b67f24a297a4f 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/actions-types'] --- import kbnActionsTypesObj from './kbn_actions_types.devdocs.json'; diff --git a/api_docs/kbn_ai_assistant.mdx b/api_docs/kbn_ai_assistant.mdx index a46f2473379c8..a36996f754c92 100644 --- a/api_docs/kbn_ai_assistant.mdx +++ b/api_docs/kbn_ai_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ai-assistant title: "@kbn/ai-assistant" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ai-assistant plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ai-assistant'] --- import kbnAiAssistantObj from './kbn_ai_assistant.devdocs.json'; diff --git a/api_docs/kbn_ai_assistant_common.mdx b/api_docs/kbn_ai_assistant_common.mdx index 333407a1d73f9..47756de9cd1a4 100644 --- a/api_docs/kbn_ai_assistant_common.mdx +++ b/api_docs/kbn_ai_assistant_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ai-assistant-common title: "@kbn/ai-assistant-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ai-assistant-common plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ai-assistant-common'] --- import kbnAiAssistantCommonObj from './kbn_ai_assistant_common.devdocs.json'; diff --git a/api_docs/kbn_ai_assistant_icon.mdx b/api_docs/kbn_ai_assistant_icon.mdx index b610f6dbf65ba..9ca8d8e8dc494 100644 --- a/api_docs/kbn_ai_assistant_icon.mdx +++ b/api_docs/kbn_ai_assistant_icon.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ai-assistant-icon title: "@kbn/ai-assistant-icon" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ai-assistant-icon plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ai-assistant-icon'] --- import kbnAiAssistantIconObj from './kbn_ai_assistant_icon.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index 71e5ef931d8d3..8511c584efa85 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: 2025-01-16 +date: 2025-01-21 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 3267ed066a53a..9e7641c635a3d 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: 2025-01-16 +date: 2025-01-21 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 e90803398f215..af90d46a4036c 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: 2025-01-16 +date: 2025-01-21 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 4cc90551b9fbb..e52d50d12e39d 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: 2025-01-16 +date: 2025-01-21 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 45c2c3e2fa554..df962bf7e655b 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: 2025-01-16 +date: 2025-01-21 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 e7c544f4ad87a..6a73831a2c09b 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: 2025-01-16 +date: 2025-01-21 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 7d7202403dc6c..bcef77c0dc7e9 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: 2025-01-16 +date: 2025-01-21 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 8e771e0abe6e1..839c1fc1a4a98 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: 2025-01-16 +date: 2025-01-21 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_grouping.mdx b/api_docs/kbn_alerts_grouping.mdx index a42900f9e167c..03a487c97ea43 100644 --- a/api_docs/kbn_alerts_grouping.mdx +++ b/api_docs/kbn_alerts_grouping.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-grouping title: "@kbn/alerts-grouping" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-grouping plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-grouping'] --- import kbnAlertsGroupingObj from './kbn_alerts_grouping.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index 4b68e91aae4a5..60dea47bb73e1 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: 2025-01-16 +date: 2025-01-21 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 514f5b8bb94ea..2902514bc858b 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: 2025-01-16 +date: 2025-01-21 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 5fc1b768187d4..048dbef126a49 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: 2025-01-16 +date: 2025-01-21 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 542d76e89b5ff..e4fe0fee0a31c 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: 2025-01-16 +date: 2025-01-21 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 f6921d15377cc..4bc9851ed81ac 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: 2025-01-16 +date: 2025-01-21 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 5431246c37712..db13a99739fda 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: 2025-01-16 +date: 2025-01-21 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 8edec8784bd86..c0faafd17d9ac 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: 2025-01-16 +date: 2025-01-21 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_types.devdocs.json b/api_docs/kbn_apm_types.devdocs.json index d251eb6019773..f01890f349f3b 100644 --- a/api_docs/kbn_apm_types.devdocs.json +++ b/api_docs/kbn_apm_types.devdocs.json @@ -2590,6 +2590,9 @@ "tags": [], "label": "original", "description": [], + "signature": [ + "string | undefined" + ], "path": "x-pack/solutions/observability/packages/kbn-apm-types/src/es_schemas/raw/fields/user_agent.ts", "deprecated": false, "trackAdoption": false diff --git a/api_docs/kbn_apm_types.mdx b/api_docs/kbn_apm_types.mdx index e6dcd659169e1..e2e2f512532a3 100644 --- a/api_docs/kbn_apm_types.mdx +++ b/api_docs/kbn_apm_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-types title: "@kbn/apm-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-types plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-types'] --- import kbnApmTypesObj from './kbn_apm_types.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index f0a554c741853..2c5e7c524cb70 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_avc_banner.mdx b/api_docs/kbn_avc_banner.mdx index d81d5ca899637..12325977e3f88 100644 --- a/api_docs/kbn_avc_banner.mdx +++ b/api_docs/kbn_avc_banner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-avc-banner title: "@kbn/avc-banner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/avc-banner plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/avc-banner'] --- import kbnAvcBannerObj from './kbn_avc_banner.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index e9ac3e8678b4e..1cb1f1901d89e 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_calculate_auto.mdx b/api_docs/kbn_calculate_auto.mdx index 8b17d00669c31..9acd39223978b 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: 2025-01-16 +date: 2025-01-21 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 03bd2b1c531dd..d1c0c6c180d76 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: 2025-01-16 +date: 2025-01-21 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 994653c8c6452..6fb2653d73b53 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] --- import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; diff --git a/api_docs/kbn_cbor.mdx b/api_docs/kbn_cbor.mdx index a9286d24607d3..b183613c2799e 100644 --- a/api_docs/kbn_cbor.mdx +++ b/api_docs/kbn_cbor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cbor title: "@kbn/cbor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cbor plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cbor'] --- import kbnCborObj from './kbn_cbor.devdocs.json'; diff --git a/api_docs/kbn_cell_actions.mdx b/api_docs/kbn_cell_actions.mdx index 8d3149c6656bf..d93f650471f63 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: 2025-01-16 +date: 2025-01-21 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 d51c282e3bda0..21a278e6b31eb 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: 2025-01-16 +date: 2025-01-21 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 0701b153aca26..a2072d7ee4fe1 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_charts_theme.mdx b/api_docs/kbn_charts_theme.mdx index 4ed1566843c91..c3160f022e85f 100644 --- a/api_docs/kbn_charts_theme.mdx +++ b/api_docs/kbn_charts_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-charts-theme title: "@kbn/charts-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/charts-theme plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/charts-theme'] --- import kbnChartsThemeObj from './kbn_charts_theme.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index 79745518d2b17..4019af1c9e3cb 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: 2025-01-16 +date: 2025-01-21 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 980e87ac961eb..dbeb1bdf4eaab 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: 2025-01-16 +date: 2025-01-21 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 c21704e0658d5..84167ac1626e4 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: 2025-01-16 +date: 2025-01-21 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 918cbabefbe2d..66c8776fe064a 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_cloud_security_posture.mdx b/api_docs/kbn_cloud_security_posture.mdx index 3ae8b2f1eb38e..15d95bae725ab 100644 --- a/api_docs/kbn_cloud_security_posture.mdx +++ b/api_docs/kbn_cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cloud-security-posture title: "@kbn/cloud-security-posture" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cloud-security-posture plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cloud-security-posture'] --- import kbnCloudSecurityPostureObj from './kbn_cloud_security_posture.devdocs.json'; diff --git a/api_docs/kbn_cloud_security_posture_common.mdx b/api_docs/kbn_cloud_security_posture_common.mdx index a020565c70768..a23f67cdb79b4 100644 --- a/api_docs/kbn_cloud_security_posture_common.mdx +++ b/api_docs/kbn_cloud_security_posture_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cloud-security-posture-common title: "@kbn/cloud-security-posture-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cloud-security-posture-common plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cloud-security-posture-common'] --- import kbnCloudSecurityPostureCommonObj from './kbn_cloud_security_posture_common.devdocs.json'; diff --git a/api_docs/kbn_cloud_security_posture_graph.mdx b/api_docs/kbn_cloud_security_posture_graph.mdx index 9714ccbba8e97..f1bdfc0b38bdf 100644 --- a/api_docs/kbn_cloud_security_posture_graph.mdx +++ b/api_docs/kbn_cloud_security_posture_graph.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cloud-security-posture-graph title: "@kbn/cloud-security-posture-graph" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cloud-security-posture-graph plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cloud-security-posture-graph'] --- import kbnCloudSecurityPostureGraphObj from './kbn_cloud_security_posture_graph.devdocs.json'; diff --git a/api_docs/kbn_code_editor.mdx b/api_docs/kbn_code_editor.mdx index c8f1c880ce68b..6a1a343ef74b5 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: 2025-01-16 +date: 2025-01-21 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 5b4d9265aeaea..ec8e171e70066 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: 2025-01-16 +date: 2025-01-21 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 05cbc3de7ebdd..5837de32bbe16 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: 2025-01-16 +date: 2025-01-21 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 a0e74b4c582f9..00d80e702071d 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: 2025-01-16 +date: 2025-01-21 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 2f22241db737a..1e06b600c86ff 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: 2025-01-16 +date: 2025-01-21 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 29b6a3a5d4df2..fd2a8c9263982 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: 2025-01-16 +date: 2025-01-21 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 492233acb17c0..af07f7c6249b4 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: 2025-01-16 +date: 2025-01-21 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 9ba6c7f67aa1a..11e1fdccb8f73 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: 2025-01-16 +date: 2025-01-21 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_content_insights_public.mdx b/api_docs/kbn_content_management_content_insights_public.mdx index 909ddfde37999..bc983bf71b42a 100644 --- a/api_docs/kbn_content_management_content_insights_public.mdx +++ b/api_docs/kbn_content_management_content_insights_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-insights-public title: "@kbn/content-management-content-insights-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-insights-public plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-insights-public'] --- import kbnContentManagementContentInsightsPublicObj from './kbn_content_management_content_insights_public.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_insights_server.mdx b/api_docs/kbn_content_management_content_insights_server.mdx index ad7f78269e3ae..268da68989d4d 100644 --- a/api_docs/kbn_content_management_content_insights_server.mdx +++ b/api_docs/kbn_content_management_content_insights_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-insights-server title: "@kbn/content-management-content-insights-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-insights-server plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-insights-server'] --- import kbnContentManagementContentInsightsServerObj from './kbn_content_management_content_insights_server.devdocs.json'; diff --git a/api_docs/kbn_content_management_favorites_common.mdx b/api_docs/kbn_content_management_favorites_common.mdx index d4843dcdfd2e2..a8a4d536b4ee3 100644 --- a/api_docs/kbn_content_management_favorites_common.mdx +++ b/api_docs/kbn_content_management_favorites_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-favorites-common title: "@kbn/content-management-favorites-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-favorites-common plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-favorites-common'] --- import kbnContentManagementFavoritesCommonObj from './kbn_content_management_favorites_common.devdocs.json'; diff --git a/api_docs/kbn_content_management_favorites_public.mdx b/api_docs/kbn_content_management_favorites_public.mdx index 887e4ce3f3d29..ffc1406ee9bd6 100644 --- a/api_docs/kbn_content_management_favorites_public.mdx +++ b/api_docs/kbn_content_management_favorites_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-favorites-public title: "@kbn/content-management-favorites-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-favorites-public plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-favorites-public'] --- import kbnContentManagementFavoritesPublicObj from './kbn_content_management_favorites_public.devdocs.json'; diff --git a/api_docs/kbn_content_management_favorites_server.mdx b/api_docs/kbn_content_management_favorites_server.mdx index 917cb328e941c..00204dfb1f9a6 100644 --- a/api_docs/kbn_content_management_favorites_server.mdx +++ b/api_docs/kbn_content_management_favorites_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-favorites-server title: "@kbn/content-management-favorites-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-favorites-server plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-favorites-server'] --- import kbnContentManagementFavoritesServerObj from './kbn_content_management_favorites_server.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 7ce0b22eda93d..923546ac63f70 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: 2025-01-16 +date: 2025-01-21 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 ac4c72d489f5f..9f88657e6642d 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: 2025-01-16 +date: 2025-01-21 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 03665aa9302ff..0c4bc4671f710 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: 2025-01-16 +date: 2025-01-21 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 3b5f82181d921..3434febac70e9 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: 2025-01-16 +date: 2025-01-21 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 eb476495998ab..9d4c612e6fdad 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: 2025-01-16 +date: 2025-01-21 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 05520ac87d84c..c1e4c7f099967 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: 2025-01-16 +date: 2025-01-21 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.mdx b/api_docs/kbn_core_analytics_browser.mdx index 9016cb481d2ee..1765745772c8f 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: 2025-01-16 +date: 2025-01-21 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 9badeae74bc34..ccaf2295d2c2e 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: 2025-01-16 +date: 2025-01-21 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 88b692976a424..a67c64791d747 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: 2025-01-16 +date: 2025-01-21 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.mdx b/api_docs/kbn_core_analytics_server.mdx index da3f23fd353d9..89119365143a6 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: 2025-01-16 +date: 2025-01-21 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 b6e017dc0587e..18637bca6207c 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: 2025-01-16 +date: 2025-01-21 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 f8e035a2568d3..0c344e8d79a3c 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: 2025-01-16 +date: 2025-01-21 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 316cc6b27eae0..36a2ba90c2be1 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: 2025-01-16 +date: 2025-01-21 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 098ee6c479a2c..31c5669e26ee4 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: 2025-01-16 +date: 2025-01-21 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 b89b9c162a50f..97aba3647ae23 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: 2025-01-16 +date: 2025-01-21 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 2c6f485549370..ef3e64f0a6280 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: 2025-01-16 +date: 2025-01-21 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 595e412761160..1c24df471cf8f 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: 2025-01-16 +date: 2025-01-21 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 0e93ae493c886..6b93038ba5999 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: 2025-01-16 +date: 2025-01-21 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 2824ca9aec906..bdd9334565e3a 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: 2025-01-16 +date: 2025-01-21 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 b1736aeff37ba..5b43b660349a1 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: 2025-01-16 +date: 2025-01-21 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 c387b9d0be0f0..90322fff8bf3b 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: 2025-01-16 +date: 2025-01-21 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 a39dbcf9071dc..253c55f82de99 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: 2025-01-16 +date: 2025-01-21 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 d35d20b1ac32c..75f7a8c2bbffc 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: 2025-01-16 +date: 2025-01-21 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 8806c9845f2bd..e96bffabb4eee 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: 2025-01-16 +date: 2025-01-21 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 6b5b74c893119..01d59ef4d5204 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: 2025-01-16 +date: 2025-01-21 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 f8648b2bd7ac1..9c98db2250a5e 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: 2025-01-16 +date: 2025-01-21 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 2a98b3f119efc..297a87130c84a 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: 2025-01-16 +date: 2025-01-21 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 a543bad09577e..23edc8ceed427 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: 2025-01-16 +date: 2025-01-21 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 7c63e11ebd220..aa57371ebbc83 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: 2025-01-16 +date: 2025-01-21 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 46f39cdb4f712..0c2de4b7d40c5 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: 2025-01-16 +date: 2025-01-21 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 bcb1abf3eeb51..c04597ea89d85 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: 2025-01-16 +date: 2025-01-21 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 1d8b3e9b1e045..34ab3e5b66426 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: 2025-01-16 +date: 2025-01-21 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 3e5a0e453f432..11eadffa940c1 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: 2025-01-16 +date: 2025-01-21 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 a858a02302f3b..dc2b7f449a4a2 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: 2025-01-16 +date: 2025-01-21 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 61068e5105bb2..a0883bed6d92d 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: 2025-01-16 +date: 2025-01-21 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 962a79e4f813a..d57cc6ddf5a9a 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: 2025-01-16 +date: 2025-01-21 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 ee860b3f0c0ca..a327c2cd12107 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: 2025-01-16 +date: 2025-01-21 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 c078fefd77b2d..68911fbe31e18 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: 2025-01-16 +date: 2025-01-21 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 8e262b971c48b..af1a7a0f8a9cf 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: 2025-01-16 +date: 2025-01-21 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 bbf9c9fe22dd2..7b379d04f6782 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: 2025-01-16 +date: 2025-01-21 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 c70b004a4a228..dfb3a70ef89db 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: 2025-01-16 +date: 2025-01-21 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 595cdddba6d5e..9ea44b91d2432 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: 2025-01-16 +date: 2025-01-21 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 2dbc9380c8e26..6194906273b15 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: 2025-01-16 +date: 2025-01-21 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 ae8dc33d2ff63..c62319895aa2a 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: 2025-01-16 +date: 2025-01-21 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 69f4f840bab5b..7067695de3877 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: 2025-01-16 +date: 2025-01-21 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 c2b705d24efd9..e6b175a4d402d 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: 2025-01-16 +date: 2025-01-21 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 e024c4a1486a3..32f6ba579e9d8 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: 2025-01-16 +date: 2025-01-21 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 124296a0b9d51..6771f6ccca5ee 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: 2025-01-16 +date: 2025-01-21 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 ca52dcfd7c0ab..b7155a13e5b83 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: 2025-01-16 +date: 2025-01-21 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 e89da132de1a1..b8da0e0ece380 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: 2025-01-16 +date: 2025-01-21 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 1e87031dba094..89183e4a512a1 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: 2025-01-16 +date: 2025-01-21 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 97000423e142a..9c6d1a8a78775 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: 2025-01-16 +date: 2025-01-21 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 b83b6e32ca822..32ba3698562c2 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: 2025-01-16 +date: 2025-01-21 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 13c2f175ca3b2..be8ee956b2813 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: 2025-01-16 +date: 2025-01-21 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 707226745f5c9..454d4f8173185 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: 2025-01-16 +date: 2025-01-21 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 d8d65b6b94a98..3b8f2726aca12 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: 2025-01-16 +date: 2025-01-21 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 5d8d6c76eb306..9c798350811ef 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: 2025-01-16 +date: 2025-01-21 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 358cad1339c5f..38e6e06d0ab40 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: 2025-01-16 +date: 2025-01-21 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 dfbbd962cbf90..824be56073304 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: 2025-01-16 +date: 2025-01-21 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 ddfe474e8b4a3..9a496aea93559 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: 2025-01-16 +date: 2025-01-21 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 f6311c5c9d640..2978a4dd55d7f 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: 2025-01-16 +date: 2025-01-21 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 fc4732bfe8a30..08b04896c5e5b 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: 2025-01-16 +date: 2025-01-21 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 7fa4f55ae6dda..a2cf06f0e695b 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: 2025-01-16 +date: 2025-01-21 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 50210083ef017..cda98044653d7 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: 2025-01-16 +date: 2025-01-21 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_feature_flags_browser.mdx b/api_docs/kbn_core_feature_flags_browser.mdx index 5401496ec0ca8..de360c3aea4c3 100644 --- a/api_docs/kbn_core_feature_flags_browser.mdx +++ b/api_docs/kbn_core_feature_flags_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-feature-flags-browser title: "@kbn/core-feature-flags-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-feature-flags-browser plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-feature-flags-browser'] --- import kbnCoreFeatureFlagsBrowserObj from './kbn_core_feature_flags_browser.devdocs.json'; diff --git a/api_docs/kbn_core_feature_flags_browser_internal.mdx b/api_docs/kbn_core_feature_flags_browser_internal.mdx index 6179c8722c6d7..e3825e159d85d 100644 --- a/api_docs/kbn_core_feature_flags_browser_internal.mdx +++ b/api_docs/kbn_core_feature_flags_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-feature-flags-browser-internal title: "@kbn/core-feature-flags-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-feature-flags-browser-internal plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-feature-flags-browser-internal'] --- import kbnCoreFeatureFlagsBrowserInternalObj from './kbn_core_feature_flags_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_feature_flags_browser_mocks.mdx b/api_docs/kbn_core_feature_flags_browser_mocks.mdx index 158df8c252b17..738d54ece058c 100644 --- a/api_docs/kbn_core_feature_flags_browser_mocks.mdx +++ b/api_docs/kbn_core_feature_flags_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-feature-flags-browser-mocks title: "@kbn/core-feature-flags-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-feature-flags-browser-mocks plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-feature-flags-browser-mocks'] --- import kbnCoreFeatureFlagsBrowserMocksObj from './kbn_core_feature_flags_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_feature_flags_server.mdx b/api_docs/kbn_core_feature_flags_server.mdx index 9174ca0f3d032..fc71d7ff63b4c 100644 --- a/api_docs/kbn_core_feature_flags_server.mdx +++ b/api_docs/kbn_core_feature_flags_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-feature-flags-server title: "@kbn/core-feature-flags-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-feature-flags-server plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-feature-flags-server'] --- import kbnCoreFeatureFlagsServerObj from './kbn_core_feature_flags_server.devdocs.json'; diff --git a/api_docs/kbn_core_feature_flags_server_internal.mdx b/api_docs/kbn_core_feature_flags_server_internal.mdx index 01339ece57a39..b350091b46cec 100644 --- a/api_docs/kbn_core_feature_flags_server_internal.mdx +++ b/api_docs/kbn_core_feature_flags_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-feature-flags-server-internal title: "@kbn/core-feature-flags-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-feature-flags-server-internal plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-feature-flags-server-internal'] --- import kbnCoreFeatureFlagsServerInternalObj from './kbn_core_feature_flags_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_feature_flags_server_mocks.mdx b/api_docs/kbn_core_feature_flags_server_mocks.mdx index 79c866ff21c3e..a6c321ec3bf8c 100644 --- a/api_docs/kbn_core_feature_flags_server_mocks.mdx +++ b/api_docs/kbn_core_feature_flags_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-feature-flags-server-mocks title: "@kbn/core-feature-flags-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-feature-flags-server-mocks plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-feature-flags-server-mocks'] --- import kbnCoreFeatureFlagsServerMocksObj from './kbn_core_feature_flags_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index 5ee7440d11ef4..f96a0b0cca938 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: 2025-01-16 +date: 2025-01-21 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 374c295446557..5e66efa5874ab 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: 2025-01-16 +date: 2025-01-21 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 fdcb44e9ef3c1..08d4ab9498515 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: 2025-01-16 +date: 2025-01-21 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 efcf7318d4a90..9e7e57043e6c5 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: 2025-01-16 +date: 2025-01-21 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 bcca64b7b7b90..568182da99cba 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: 2025-01-16 +date: 2025-01-21 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 1ce0098fa3507..dbef6f824952b 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: 2025-01-16 +date: 2025-01-21 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 298a7a5e04e78..83b03e1d87f67 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: 2025-01-16 +date: 2025-01-21 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 b3eac0e34a3b8..753547f3122ce 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: 2025-01-16 +date: 2025-01-21 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 fcb8de3e08114..2de300a0d86fb 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: 2025-01-16 +date: 2025-01-21 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.devdocs.json b/api_docs/kbn_core_http_router_server_internal.devdocs.json index f30f0747890c0..8fa0e89019c52 100644 --- a/api_docs/kbn_core_http_router_server_internal.devdocs.json +++ b/api_docs/kbn_core_http_router_server_internal.devdocs.json @@ -65,7 +65,7 @@ "label": "from", "description": [], "signature": [ - "({ router, log, defaultHandlerResolutionStrategy, isDev, useVersionResolutionStrategyForInternalPaths, }: ", + "({ router, log, defaultHandlerResolutionStrategy, env, useVersionResolutionStrategyForInternalPaths, }: ", "VersionedRouterArgs", ") => ", "CoreVersionedRouter" @@ -79,7 +79,7 @@ "id": "def-server.CoreVersionedRouter.from.$1", "type": "Object", "tags": [], - "label": "{\n router,\n log,\n defaultHandlerResolutionStrategy,\n isDev,\n useVersionResolutionStrategyForInternalPaths,\n }", + "label": "{\n router,\n log,\n defaultHandlerResolutionStrategy,\n env,\n useVersionResolutionStrategyForInternalPaths,\n }", "description": [], "signature": [ "VersionedRouterArgs" @@ -569,6 +569,56 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.getWarningHeaderMessageFromRouteDeprecation", + "type": "Function", + "tags": [], + "label": "getWarningHeaderMessageFromRouteDeprecation", + "description": [], + "signature": [ + "(deprecationObject: ", + "RouteDeprecationInfo", + ", kibanaVersion: string) => string" + ], + "path": "src/core/packages/http/router-server-internal/src/get_warning_header_message.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.getWarningHeaderMessageFromRouteDeprecation.$1", + "type": "Object", + "tags": [], + "label": "deprecationObject", + "description": [], + "signature": [ + "RouteDeprecationInfo" + ], + "path": "src/core/packages/http/router-server-internal/src/get_warning_header_message.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.getWarningHeaderMessageFromRouteDeprecation.$2", + "type": "string", + "tags": [], + "label": "kibanaVersion", + "description": [], + "signature": [ + "string" + ], + "path": "src/core/packages/http/router-server-internal/src/get_warning_header_message.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/core-http-router-server-internal", "id": "def-server.isSafeMethod", diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index 5323cf25964e2..355c434e41a95 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 54 | 7 | 54 | 0 | +| 57 | 7 | 57 | 0 | ## Server diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index a1f166fd9e5da..b927e3d8aad52 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: 2025-01-16 +date: 2025-01-21 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 c378e0b2c6c72..5460beb36c312 100644 --- a/api_docs/kbn_core_http_server.devdocs.json +++ b/api_docs/kbn_core_http_server.devdocs.json @@ -4060,6 +4060,10 @@ "plugin": "searchPlayground", "path": "x-pack/solutions/search/plugins/search_playground/server/routes.ts" }, + { + "plugin": "searchSynonyms", + "path": "x-pack/solutions/search/plugins/search_synonyms/server/routes.ts" + }, { "plugin": "serverlessSearch", "path": "x-pack/solutions/search/plugins/serverless_search/server/routes/api_key_routes.ts" @@ -9992,6 +9996,23 @@ "path": "src/core/packages/http/server/src/lifecycle/on_pre_response.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-http-server", + "id": "def-server.OnPreResponseInfo.headers", + "type": "CompoundType", + "tags": [], + "label": "headers", + "description": [ + "So any pre response handler can check the headers if needed, to avoid an overwrite for example" + ], + "signature": [ + "ResponseHeaders", + " | undefined" + ], + "path": "src/core/packages/http/server/src/lifecycle/on_pre_response.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -11424,7 +11445,7 @@ "tags": [], "label": "message", "description": [ - "\nThe description message to be displayed for the deprecation.\nCheck the README for writing deprecations in `src/core/server/deprecations/README.mdx`" + "\nThe description message to be displayed for the deprecation.\nThis will also appear in the '299 Kibana-{version} {message}' header warning when someone calls the route.\nKeep the message concise to avoid long header values. It is recommended to keep the message under 255 characters.\nCheck the README for writing deprecations in `src/core/server/deprecations/README.mdx`" ], "signature": [ "string | undefined" @@ -14311,6 +14332,10 @@ "plugin": "telemetry", "path": "src/platform/plugins/shared/telemetry/server/routes/telemetry_usage_stats.ts" }, + { + "plugin": "telemetry", + "path": "src/platform/plugins/shared/telemetry/server/local_shipper/initialize_local_shipper.ts" + }, { "plugin": "transform", "path": "x-pack/platform/plugins/private/transform/server/routes/api/field_histograms/register_route.ts" @@ -14873,35 +14898,35 @@ }, { "plugin": "securitySolution", - "path": "x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts" + "path": "x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts" }, { "plugin": "securitySolution", - "path": "x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts" + "path": "x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/bootstrap_prebuilt_rules/bootstrap_prebuilt_rules.ts" }, { "plugin": "securitySolution", - "path": "x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/export_rules/route.ts" + "path": "x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/api/create_legacy_notification/route.ts" }, { "plugin": "securitySolution", - "path": "x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts" + "path": "x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts" }, { "plugin": "securitySolution", - "path": "x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/route.ts" + "path": "x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts" }, { "plugin": "securitySolution", - "path": "x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts" + "path": "x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/export_rules/route.ts" }, { "plugin": "securitySolution", - "path": "x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/bootstrap_prebuilt_rules/bootstrap_prebuilt_rules.ts" + "path": "x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts" }, { "plugin": "securitySolution", - "path": "x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/api/create_legacy_notification/route.ts" + "path": "x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/route.ts" }, { "plugin": "securitySolution", @@ -15033,7 +15058,7 @@ }, { "plugin": "securitySolution", - "path": "x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/install_translated.ts" + "path": "x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/routes/enablement.ts" }, { "plugin": "securitySolution", @@ -15549,6 +15574,10 @@ "plugin": "securitySolution", "path": "x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/routes/delete.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/routes/delete.ts" + }, { "plugin": "metricsDataAccess", "path": "x-pack/solutions/observability/plugins/metrics_data_access/server/lib/adapters/framework/kibana_framework_adapter.ts" diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index 6170326f86d0c..685dcd6bed670 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] --- import kbnCoreHttpServerObj from './kbn_core_http_server.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 568 | 2 | 243 | 0 | +| 569 | 2 | 243 | 0 | ## Server diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index 7df551e2f5a8d..3628bc856ce0c 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: 2025-01-16 +date: 2025-01-21 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 67cf7cea7c0dd..2aba169f9d520 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: 2025-01-16 +date: 2025-01-21 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_http_server_utils.mdx b/api_docs/kbn_core_http_server_utils.mdx index 3fec7938e4563..81af6b5a3959b 100644 --- a/api_docs/kbn_core_http_server_utils.mdx +++ b/api_docs/kbn_core_http_server_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-utils title: "@kbn/core-http-server-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-utils plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-utils'] --- import kbnCoreHttpServerUtilsObj from './kbn_core_http_server_utils.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index 1a61ff8731b17..7753e3b75ea51 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: 2025-01-16 +date: 2025-01-21 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 7974d49e9fd98..98cda3564c991 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: 2025-01-16 +date: 2025-01-21 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 2e44d67372033..6182d4c772bfe 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: 2025-01-16 +date: 2025-01-21 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 f0953bb38eb58..d42df1d62a841 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: 2025-01-16 +date: 2025-01-21 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 d53da827bb5bf..29f0d89291b2d 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: 2025-01-16 +date: 2025-01-21 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 4d47e6e8667d5..62fec3e508f4f 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: 2025-01-16 +date: 2025-01-21 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 17c81a5263b25..06a127b0a8659 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: 2025-01-16 +date: 2025-01-21 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 386753c7e9dac..06d5c99f3196c 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: 2025-01-16 +date: 2025-01-21 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 f5e372a833d8d..13e670638190a 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: 2025-01-16 +date: 2025-01-21 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 cf45767497dc6..e8990bd7fe99b 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: 2025-01-16 +date: 2025-01-21 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 2e2d7c7227b28..a15148ec01ab4 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: 2025-01-16 +date: 2025-01-21 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 dc6f2703952a1..30a31d4659319 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: 2025-01-16 +date: 2025-01-21 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 e7c1fe81e4bca..e1ef99fcef2bd 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: 2025-01-16 +date: 2025-01-21 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 a872f75524625..1cac81a5615bb 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: 2025-01-16 +date: 2025-01-21 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 6662c90e46358..3db69765702d9 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: 2025-01-16 +date: 2025-01-21 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 d4f4a08c03c1c..7c7eb32a581d7 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: 2025-01-16 +date: 2025-01-21 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 44a02c7d7f646..d940ebf4dc0eb 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: 2025-01-16 +date: 2025-01-21 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 f0546339bc728..9272cf5693069 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: 2025-01-16 +date: 2025-01-21 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 876e001faf9a3..3753e351b1c35 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: 2025-01-16 +date: 2025-01-21 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 c72b5bdf33b93..0df34e08e40cc 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: 2025-01-16 +date: 2025-01-21 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 226913a4db6a8..5592c354a8940 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: 2025-01-16 +date: 2025-01-21 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 045a45d811cff..9f44dc6309e29 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: 2025-01-16 +date: 2025-01-21 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 e37305e70be0a..5b70f981e2223 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: 2025-01-16 +date: 2025-01-21 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 ac946ba851eb0..d3dcf9af582eb 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: 2025-01-16 +date: 2025-01-21 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 6274c2f375240..080573225c73b 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: 2025-01-16 +date: 2025-01-21 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 7cf2a9946f81e..b956befaa93e2 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: 2025-01-16 +date: 2025-01-21 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 cdf7dd8185a5f..2b9eaad882f9c 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: 2025-01-16 +date: 2025-01-21 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 a2fdd0c42ef1b..27cfc2a791282 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: 2025-01-16 +date: 2025-01-21 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 e5fd199579f51..6fbfdbceceb10 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: 2025-01-16 +date: 2025-01-21 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 42066b463af5a..ebc6700293865 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: 2025-01-16 +date: 2025-01-21 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 f62945555ccae..3a92541f914d2 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: 2025-01-16 +date: 2025-01-21 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 e67e9394de570..cceb57c3795c9 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: 2025-01-16 +date: 2025-01-21 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 4fd31bcd3d8e0..3b4d155dc9943 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: 2025-01-16 +date: 2025-01-21 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 c4e86daff03a8..0f5f26c4c3dbb 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: 2025-01-16 +date: 2025-01-21 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 de24c0cc6156f..0a590bbb30d15 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: 2025-01-16 +date: 2025-01-21 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 842dd9bdaa5b3..0c568efab322f 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: 2025-01-16 +date: 2025-01-21 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 83cd8369bead4..7767bf61b0223 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: 2025-01-16 +date: 2025-01-21 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 bafb0870b8076..cc33cf7efdd4a 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: 2025-01-16 +date: 2025-01-21 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 28198791946d9..e881cdebbc126 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: 2025-01-16 +date: 2025-01-21 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 a062c97ff8d02..512788a83b471 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: 2025-01-16 +date: 2025-01-21 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.mdx b/api_docs/kbn_core_rendering_browser.mdx index 43bbf4e3a5750..b6d7dc64819cb 100644 --- a/api_docs/kbn_core_rendering_browser.mdx +++ b/api_docs/kbn_core_rendering_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser title: "@kbn/core-rendering-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-browser'] --- import kbnCoreRenderingBrowserObj from './kbn_core_rendering_browser.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index d4e71d312f538..3988a8e66e8c8 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: 2025-01-16 +date: 2025-01-21 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 d4d507ed63a7a..7ce537543bce4 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: 2025-01-16 +date: 2025-01-21 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 5910b5d77a4b6..1f96538d9dfb4 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: 2025-01-16 +date: 2025-01-21 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 7bba013c66bec..2443294f4b9bc 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: 2025-01-16 +date: 2025-01-21 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 589d2a1ff7494..c418826987165 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: 2025-01-16 +date: 2025-01-21 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 f6d13443c560c..51c5ae3525760 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: 2025-01-16 +date: 2025-01-21 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 9d2ece3589647..2e20765155501 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: 2025-01-16 +date: 2025-01-21 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 610f6e5cf8d5b..d24791fc11887 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: 2025-01-16 +date: 2025-01-21 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 7578525fcddcb..a419ebbca4489 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: 2025-01-16 +date: 2025-01-21 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 1a128229b4aad..45a800a4c4d53 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: 2025-01-16 +date: 2025-01-21 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 da3df8b69a6f8..3ef2242502e23 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: 2025-01-16 +date: 2025-01-21 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 62481e607efc4..4b042d20fd952 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: 2025-01-16 +date: 2025-01-21 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 8d5f5de06fa9d..c3abffff6f5a1 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: 2025-01-16 +date: 2025-01-21 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 f04e46f8c4894..5f25340946a38 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: 2025-01-16 +date: 2025-01-21 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 eb1344e288883..fd6e4c6ddc84b 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: 2025-01-16 +date: 2025-01-21 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 0ee34311c7ef4..e35be7a83e9b0 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: 2025-01-16 +date: 2025-01-21 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 37e0eda86248f..eb152b75fc50f 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: 2025-01-16 +date: 2025-01-21 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 c6c3d06efc1d3..7e1cf2d4b66ad 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: 2025-01-16 +date: 2025-01-21 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 345f757ff1762..991e91edc1815 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: 2025-01-16 +date: 2025-01-21 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 36c4a3bf3d0b8..6038cf799222c 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: 2025-01-16 +date: 2025-01-21 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 0b3a91a524e90..b56a6c965e86c 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: 2025-01-16 +date: 2025-01-21 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 64d9290be6940..537e18beba232 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: 2025-01-16 +date: 2025-01-21 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 c8325ace92b97..f7a2a6cbda7c6 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: 2025-01-16 +date: 2025-01-21 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 e211f68acc0e7..bf077b4548cdf 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: 2025-01-16 +date: 2025-01-21 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 169f5e8f08832..9205797788cc6 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: 2025-01-16 +date: 2025-01-21 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 cdf2d4e22d28f..13b09a8372d86 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: 2025-01-16 +date: 2025-01-21 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 c41c2dc457747..5a66332ab1662 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: 2025-01-16 +date: 2025-01-21 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 8c10aae73ac66..f902590260a22 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: 2025-01-16 +date: 2025-01-21 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 442f33f958750..8c87c3b4f8b82 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: 2025-01-16 +date: 2025-01-21 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_server.mdx b/api_docs/kbn_core_status_server.mdx index 49835667ef8b9..f4c1e7b15f1e8 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: 2025-01-16 +date: 2025-01-21 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 cb31f709b5413..d6a1602f30d73 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: 2025-01-16 +date: 2025-01-21 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 054fc100d313a..33d7779efa69d 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: 2025-01-16 +date: 2025-01-21 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 54ad07804684d..5951226911b6f 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: 2025-01-16 +date: 2025-01-21 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 5891a8d70fee6..fb6dfbf75e07e 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: 2025-01-16 +date: 2025-01-21 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 10a3274ddf430..7844fdba1445f 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: 2025-01-16 +date: 2025-01-21 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 8d0c56dcc42b5..aa7c3be019f4f 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: 2025-01-16 +date: 2025-01-21 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 f577d447cf5e0..a8b5a1c4bd9d7 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: 2025-01-16 +date: 2025-01-21 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 cc68574aa26bf..386e390fd7aee 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: 2025-01-16 +date: 2025-01-21 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 edc740cfc6cbd..70b74cbe21919 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: 2025-01-16 +date: 2025-01-21 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_internal.mdx b/api_docs/kbn_core_theme_browser_internal.mdx index 0f09106d76fca..b36b420fc7f26 100644 --- a/api_docs/kbn_core_theme_browser_internal.mdx +++ b/api_docs/kbn_core_theme_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-internal title: "@kbn/core-theme-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-internal plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-internal'] --- import kbnCoreThemeBrowserInternalObj from './kbn_core_theme_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index a514eaac38269..a6df82b890091 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: 2025-01-16 +date: 2025-01-21 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 0c69b69ed0631..57647aa6241f0 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: 2025-01-16 +date: 2025-01-21 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 7b4255e8e9dc3..053c694e488aa 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: 2025-01-16 +date: 2025-01-21 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 c26f8e7752152..8e6ab60bbc687 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: 2025-01-16 +date: 2025-01-21 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.devdocs.json b/api_docs/kbn_core_ui_settings_common.devdocs.json index 4fba867fa5ccb..316b1a99db4dc 100644 --- a/api_docs/kbn_core_ui_settings_common.devdocs.json +++ b/api_docs/kbn_core_ui_settings_common.devdocs.json @@ -96,7 +96,7 @@ "label": "parseThemeNameValue", "description": [], "signature": [ - "(value: unknown) => string" + "(value: unknown) => \"amsterdam\" | \"borealis\"" ], "path": "src/core/packages/ui-settings/common/src/theme.ts", "deprecated": false, @@ -644,7 +644,7 @@ "label": "DEFAULT_THEME_NAME", "description": [], "signature": [ - "\"amsterdam\"" + "\"borealis\"" ], "path": "src/core/packages/ui-settings/common/src/theme.ts", "deprecated": false, @@ -683,21 +683,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "@kbn/core-ui-settings-common", - "id": "def-common.SUPPORTED_THEME_NAMES", - "type": "Array", - "tags": [], - "label": "SUPPORTED_THEME_NAMES", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/core/packages/ui-settings/common/src/theme.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "@kbn/core-ui-settings-common", "id": "def-common.ThemeName", @@ -706,7 +691,7 @@ "label": "ThemeName", "description": [], "signature": [ - "string" + "\"amsterdam\" | \"borealis\"" ], "path": "src/core/packages/ui-settings/common/src/theme.ts", "deprecated": false, @@ -811,6 +796,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.SUPPORTED_THEME_NAMES", + "type": "Object", + "tags": [], + "label": "SUPPORTED_THEME_NAMES", + "description": [], + "signature": [ + "readonly [\"amsterdam\", \"borealis\"]" + ], + "path": "src/core/packages/ui-settings/common/src/theme.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/core-ui-settings-common", "id": "def-common.SUPPORTED_THEME_TAGS", diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx index 8fa96b4c1404b..160173150254a 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: 2025-01-16 +date: 2025-01-21 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 843bb921c9e84..2bf9cbcd09058 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: 2025-01-16 +date: 2025-01-21 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.devdocs.json b/api_docs/kbn_core_ui_settings_server_internal.devdocs.json index d42798073bd05..c4eae145b9fc6 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.devdocs.json +++ b/api_docs/kbn_core_ui_settings_server_internal.devdocs.json @@ -321,7 +321,7 @@ "section": "def-common.Type", "text": "Type" }, - " | undefined>; }>" + " | undefined>; }>" ], "path": "src/core/packages/ui-settings/server-internal/src/ui_settings_config.ts", "deprecated": false, diff --git a/api_docs/kbn_core_ui_settings_server_internal.mdx b/api_docs/kbn_core_ui_settings_server_internal.mdx index 6f454596f2047..d74660cc520e3 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: 2025-01-16 +date: 2025-01-21 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 774cef4e271b4..4cc09dde99d97 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: 2025-01-16 +date: 2025-01-21 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 054b8909bd5bb..7804b0a708e2a 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: 2025-01-16 +date: 2025-01-21 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 bc188aac9704f..0536f47171248 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: 2025-01-16 +date: 2025-01-21 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 de6de3e1a39b5..bc537fce497cd 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: 2025-01-16 +date: 2025-01-21 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 25259b00be877..a2b4424381f9f 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: 2025-01-16 +date: 2025-01-21 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 51547e3dfbe61..e3c509db48f56 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: 2025-01-16 +date: 2025-01-21 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 298eb7acb5570..b48833992dd77 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: 2025-01-16 +date: 2025-01-21 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 e13277517894e..26e206955e77f 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: 2025-01-16 +date: 2025-01-21 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 397261d05f29c..f7dacd221663c 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: 2025-01-16 +date: 2025-01-21 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 97b6409155f74..333098bce0dc5 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: 2025-01-16 +date: 2025-01-21 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 5a6f905e5a7aa..068f44b0c792d 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: 2025-01-16 +date: 2025-01-21 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 e37bfca411d1c..836fdc6667814 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: 2025-01-16 +date: 2025-01-21 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 2f0c13de9bcc6..94dc56d031259 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: 2025-01-16 +date: 2025-01-21 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 fd0907395c6b0..3cdf0a43ef5f2 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: 2025-01-16 +date: 2025-01-21 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 d19529db02107..b1ce962802a45 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: 2025-01-16 +date: 2025-01-21 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 b4961523cc02a..c99d49903dd26 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: 2025-01-16 +date: 2025-01-21 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 6d66ef3163200..7ca730f986987 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: 2025-01-16 +date: 2025-01-21 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 1bab589dc79c2..6a1fe9460ed04 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: 2025-01-16 +date: 2025-01-21 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 d570d9c25956e..faf50a208a343 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: 2025-01-16 +date: 2025-01-21 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 6fdde36923b0c..a8f63d5518550 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: 2025-01-16 +date: 2025-01-21 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 eedbb96b000ed..50a972b81cdf4 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: 2025-01-16 +date: 2025-01-21 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.devdocs.json b/api_docs/kbn_data_view_utils.devdocs.json index 63cde7b6efec9..d6d84647037c5 100644 --- a/api_docs/kbn_data_view_utils.devdocs.json +++ b/api_docs/kbn_data_view_utils.devdocs.json @@ -83,7 +83,7 @@ "label": "createRegExpPatternFrom", "description": [], "signature": [ - "(basePatterns: string | string[]) => RegExp" + "(basePatterns: string | string[], selector: Selector) => RegExp" ], "path": "src/platform/packages/shared/kbn-data-view-utils/src/utils/create_regexp_pattern_from.ts", "deprecated": false, @@ -103,6 +103,21 @@ "deprecated": false, "trackAdoption": false, "isRequired": true + }, + { + "parentPluginId": "@kbn/data-view-utils", + "id": "def-common.createRegExpPatternFrom.$2", + "type": "CompoundType", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "Selector" + ], + "path": "src/platform/packages/shared/kbn-data-view-utils/src/utils/create_regexp_pattern_from.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true } ], "returnComment": [], diff --git a/api_docs/kbn_data_view_utils.mdx b/api_docs/kbn_data_view_utils.mdx index 4633de2766dd0..d9130e46abc0c 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-view-utils'] --- import kbnDataViewUtilsObj from './kbn_data_view_utils.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 7 | 0 | 5 | 0 | +| 8 | 0 | 6 | 0 | ## Common diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index b36169744ef61..e89fbe2d743e4 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: 2025-01-16 +date: 2025-01-21 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 206f4df6829b6..90c3264104b0c 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: 2025-01-16 +date: 2025-01-21 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 224a8801f6c3e..34d1127623b33 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: 2025-01-16 +date: 2025-01-21 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 7607054073676..9b0121134ab51 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: 2025-01-16 +date: 2025-01-21 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 09eb226557462..0508f83c04c7d 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: 2025-01-16 +date: 2025-01-21 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 116b6a2a7904c..cdcb6ce205f97 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: 2025-01-16 +date: 2025-01-21 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 3b97c1e12a7bb..7da164fec6382 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: 2025-01-16 +date: 2025-01-21 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 f80d01aa66506..2078527870d3c 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: 2025-01-16 +date: 2025-01-21 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 b2647e39dafd0..1b4ff48536f38 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: 2025-01-16 +date: 2025-01-21 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 3bb3874407504..1034b61d46a6a 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: 2025-01-16 +date: 2025-01-21 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 f7413e8577db8..88f316d341330 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: 2025-01-16 +date: 2025-01-21 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 bde3b43af91bf..65b96212a5ffd 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: 2025-01-16 +date: 2025-01-21 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 d73bc5e6efad7..2b9a591fa919e 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: 2025-01-16 +date: 2025-01-21 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 77c2e86d01943..1b2df0f169484 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: 2025-01-16 +date: 2025-01-21 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 5dd69311e22a6..c6b832645859a 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: 2025-01-16 +date: 2025-01-21 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 13e7d3732ce5e..34478bd54a978 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: 2025-01-16 +date: 2025-01-21 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 87b1751049fad..c2b97cb040a19 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: 2025-01-16 +date: 2025-01-21 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 4f0d3760046b0..e93a351a2b1bc 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_discover_contextual_components.mdx b/api_docs/kbn_discover_contextual_components.mdx index 6cb74f9a55e92..9f810a0cf8d24 100644 --- a/api_docs/kbn_discover_contextual_components.mdx +++ b/api_docs/kbn_discover_contextual_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-discover-contextual-components title: "@kbn/discover-contextual-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/discover-contextual-components plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/discover-contextual-components'] --- import kbnDiscoverContextualComponentsObj from './kbn_discover_contextual_components.devdocs.json'; diff --git a/api_docs/kbn_discover_utils.mdx b/api_docs/kbn_discover_utils.mdx index 721778199bbd4..b61521c7124b5 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: 2025-01-16 +date: 2025-01-21 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 cff037d73274c..7c2364ebcff03 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: 2025-01-16 +date: 2025-01-21 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 68c31eb2e8e82..cfa7287d47f8c 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: 2025-01-16 +date: 2025-01-21 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 d44163b6b8e43..9fba031a66284 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: 2025-01-16 +date: 2025-01-21 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_tools.mdx b/api_docs/kbn_ebt_tools.mdx index 4da01a54da1e4..f23c088dc6b10 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: 2025-01-16 +date: 2025-01-21 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 86cd026d64122..024b80b881947 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: 2025-01-16 +date: 2025-01-21 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 38cb6439dee6f..69bfd5febc3a2 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: 2025-01-16 +date: 2025-01-21 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 7a4d6d65cfa5a..f8a53049d4a7f 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: 2025-01-16 +date: 2025-01-21 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 2d07ae8be637a..3f03333bc8172 100644 --- a/api_docs/kbn_elastic_assistant_common.devdocs.json +++ b/api_docs/kbn_elastic_assistant_common.devdocs.json @@ -1703,7 +1703,7 @@ "label": "ConversationUpdateProps", "description": [], "signature": [ - "{ id: string; title?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }" + "{ id: string; title?: string | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }" ], "path": "x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.gen.ts", "deprecated": false, @@ -3645,7 +3645,7 @@ "label": "PerformBulkActionRequestBody", "description": [], "signature": [ - "{ create?: { title: string; id?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; isDefault?: boolean | undefined; excludeFromLastConversationStorage?: boolean | undefined; }[] | undefined; update?: { id: string; title?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }[] | undefined; delete?: { ids?: string[] | undefined; query?: string | undefined; } | undefined; }" + "{ create?: { title: string; id?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; isDefault?: boolean | undefined; excludeFromLastConversationStorage?: boolean | undefined; }[] | undefined; update?: { id: string; title?: string | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }[] | undefined; delete?: { ids?: string[] | undefined; query?: string | undefined; } | undefined; }" ], "path": "x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/schemas/conversations/bulk_crud_conversations_route.gen.ts", "deprecated": false, @@ -3660,7 +3660,7 @@ "label": "PerformBulkActionRequestBodyInput", "description": [], "signature": [ - "{ create?: { title: string; id?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; isDefault?: boolean | undefined; excludeFromLastConversationStorage?: boolean | undefined; }[] | undefined; update?: { id: string; title?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }[] | undefined; delete?: { ids?: string[] | undefined; query?: string | undefined; } | undefined; }" + "{ create?: { title: string; id?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; isDefault?: boolean | undefined; excludeFromLastConversationStorage?: boolean | undefined; }[] | undefined; update?: { id: string; title?: string | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }[] | undefined; delete?: { ids?: string[] | undefined; query?: string | undefined; } | undefined; }" ], "path": "x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/schemas/conversations/bulk_crud_conversations_route.gen.ts", "deprecated": false, @@ -4131,7 +4131,7 @@ "label": "UpdateConversationRequestBody", "description": [], "signature": [ - "{ id: string; title?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }" + "{ id: string; title?: string | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }" ], "path": "x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/schemas/conversations/crud_conversation_route.gen.ts", "deprecated": false, @@ -4146,7 +4146,7 @@ "label": "UpdateConversationRequestBodyInput", "description": [], "signature": [ - "{ id: string; title?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }" + "{ id: string; title?: string | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }" ], "path": "x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/schemas/conversations/crud_conversation_route.gen.ts", "deprecated": false, @@ -5009,7 +5009,7 @@ "label": "ConversationUpdateProps", "description": [], "signature": [ - "Zod.ZodObject<{ id: Zod.ZodEffects; title: Zod.ZodOptional; category: Zod.ZodOptional>; messages: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\">>>; role: Zod.ZodEnum<[\"system\", \"user\", \"assistant\"]>; timestamp: Zod.ZodEffects; isError: Zod.ZodOptional; traceData: Zod.ZodOptional; traceId: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { transactionId?: string | undefined; traceId?: string | undefined; }, { transactionId?: string | undefined; traceId?: string | undefined; }>>; }, \"strip\", Zod.ZodTypeAny, { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }, { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }>, \"many\">>; apiConfig: Zod.ZodOptional; provider: Zod.ZodOptional>; model: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; }, { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; }>>; summary: Zod.ZodOptional; timestamp: Zod.ZodOptional>; public: Zod.ZodOptional; confidence: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; }, { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; }>>; excludeFromLastConversationStorage: Zod.ZodOptional; replacements: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodString, \"strip\">>>; }, \"strip\", Zod.ZodTypeAny, { id: string; title?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }, { id: string; title?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }>" + "Zod.ZodObject<{ id: Zod.ZodEffects; title: Zod.ZodOptional; category: Zod.ZodOptional>; messages: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\">>>; role: Zod.ZodEnum<[\"system\", \"user\", \"assistant\"]>; timestamp: Zod.ZodEffects; isError: Zod.ZodOptional; traceData: Zod.ZodOptional; traceId: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { transactionId?: string | undefined; traceId?: string | undefined; }, { transactionId?: string | undefined; traceId?: string | undefined; }>>; }, \"strip\", Zod.ZodTypeAny, { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }, { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }>, \"many\">>; apiConfig: Zod.ZodOptional; provider: Zod.ZodOptional>; model: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; }, { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; }>>; summary: Zod.ZodOptional; timestamp: Zod.ZodOptional>; public: Zod.ZodOptional; confidence: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; }, { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; }>>; excludeFromLastConversationStorage: Zod.ZodOptional; replacements: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodString, \"strip\">>>; }, \"strip\", Zod.ZodTypeAny, { id: string; title?: string | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }, { id: string; title?: string | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }>" ], "path": "x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.gen.ts", "deprecated": false, @@ -6301,7 +6301,7 @@ "label": "PerformBulkActionRequestBody", "description": [], "signature": [ - "Zod.ZodObject<{ delete: Zod.ZodOptional; ids: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { ids?: string[] | undefined; query?: string | undefined; }, { ids?: string[] | undefined; query?: string | undefined; }>>; create: Zod.ZodOptional; title: Zod.ZodString; category: Zod.ZodOptional>; messages: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\">>>; role: Zod.ZodEnum<[\"system\", \"user\", \"assistant\"]>; timestamp: Zod.ZodEffects; isError: Zod.ZodOptional; traceData: Zod.ZodOptional; traceId: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { transactionId?: string | undefined; traceId?: string | undefined; }, { transactionId?: string | undefined; traceId?: string | undefined; }>>; }, \"strip\", Zod.ZodTypeAny, { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }, { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }>, \"many\">>; apiConfig: Zod.ZodOptional; provider: Zod.ZodOptional>; model: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; }, { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; }>>; isDefault: Zod.ZodOptional; excludeFromLastConversationStorage: Zod.ZodOptional; replacements: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodString, \"strip\">>>; }, \"strip\", Zod.ZodTypeAny, { title: string; id?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; isDefault?: boolean | undefined; excludeFromLastConversationStorage?: boolean | undefined; }, { title: string; id?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; isDefault?: boolean | undefined; excludeFromLastConversationStorage?: boolean | undefined; }>, \"many\">>; update: Zod.ZodOptional; title: Zod.ZodOptional; category: Zod.ZodOptional>; messages: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\">>>; role: Zod.ZodEnum<[\"system\", \"user\", \"assistant\"]>; timestamp: Zod.ZodEffects; isError: Zod.ZodOptional; traceData: Zod.ZodOptional; traceId: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { transactionId?: string | undefined; traceId?: string | undefined; }, { transactionId?: string | undefined; traceId?: string | undefined; }>>; }, \"strip\", Zod.ZodTypeAny, { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }, { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }>, \"many\">>; apiConfig: Zod.ZodOptional; provider: Zod.ZodOptional>; model: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; }, { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; }>>; summary: Zod.ZodOptional; timestamp: Zod.ZodOptional>; public: Zod.ZodOptional; confidence: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; }, { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; }>>; excludeFromLastConversationStorage: Zod.ZodOptional; replacements: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodString, \"strip\">>>; }, \"strip\", Zod.ZodTypeAny, { id: string; title?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }, { id: string; title?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }>, \"many\">>; }, \"strip\", Zod.ZodTypeAny, { create?: { title: string; id?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; isDefault?: boolean | undefined; excludeFromLastConversationStorage?: boolean | undefined; }[] | undefined; update?: { id: string; title?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }[] | undefined; delete?: { ids?: string[] | undefined; query?: string | undefined; } | undefined; }, { create?: { title: string; id?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; isDefault?: boolean | undefined; excludeFromLastConversationStorage?: boolean | undefined; }[] | undefined; update?: { id: string; title?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }[] | undefined; delete?: { ids?: string[] | undefined; query?: string | undefined; } | undefined; }>" + "Zod.ZodObject<{ delete: Zod.ZodOptional; ids: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { ids?: string[] | undefined; query?: string | undefined; }, { ids?: string[] | undefined; query?: string | undefined; }>>; create: Zod.ZodOptional; title: Zod.ZodString; category: Zod.ZodOptional>; messages: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\">>>; role: Zod.ZodEnum<[\"system\", \"user\", \"assistant\"]>; timestamp: Zod.ZodEffects; isError: Zod.ZodOptional; traceData: Zod.ZodOptional; traceId: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { transactionId?: string | undefined; traceId?: string | undefined; }, { transactionId?: string | undefined; traceId?: string | undefined; }>>; }, \"strip\", Zod.ZodTypeAny, { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }, { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }>, \"many\">>; apiConfig: Zod.ZodOptional; provider: Zod.ZodOptional>; model: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; }, { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; }>>; isDefault: Zod.ZodOptional; excludeFromLastConversationStorage: Zod.ZodOptional; replacements: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodString, \"strip\">>>; }, \"strip\", Zod.ZodTypeAny, { title: string; id?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; isDefault?: boolean | undefined; excludeFromLastConversationStorage?: boolean | undefined; }, { title: string; id?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; isDefault?: boolean | undefined; excludeFromLastConversationStorage?: boolean | undefined; }>, \"many\">>; update: Zod.ZodOptional; title: Zod.ZodOptional; category: Zod.ZodOptional>; messages: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\">>>; role: Zod.ZodEnum<[\"system\", \"user\", \"assistant\"]>; timestamp: Zod.ZodEffects; isError: Zod.ZodOptional; traceData: Zod.ZodOptional; traceId: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { transactionId?: string | undefined; traceId?: string | undefined; }, { transactionId?: string | undefined; traceId?: string | undefined; }>>; }, \"strip\", Zod.ZodTypeAny, { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }, { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }>, \"many\">>; apiConfig: Zod.ZodOptional; provider: Zod.ZodOptional>; model: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; }, { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; }>>; summary: Zod.ZodOptional; timestamp: Zod.ZodOptional>; public: Zod.ZodOptional; confidence: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; }, { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; }>>; excludeFromLastConversationStorage: Zod.ZodOptional; replacements: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodString, \"strip\">>>; }, \"strip\", Zod.ZodTypeAny, { id: string; title?: string | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }, { id: string; title?: string | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }>, \"many\">>; }, \"strip\", Zod.ZodTypeAny, { create?: { title: string; id?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; isDefault?: boolean | undefined; excludeFromLastConversationStorage?: boolean | undefined; }[] | undefined; update?: { id: string; title?: string | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }[] | undefined; delete?: { ids?: string[] | undefined; query?: string | undefined; } | undefined; }, { create?: { title: string; id?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; isDefault?: boolean | undefined; excludeFromLastConversationStorage?: boolean | undefined; }[] | undefined; update?: { id: string; title?: string | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }[] | undefined; delete?: { ids?: string[] | undefined; query?: string | undefined; } | undefined; }>" ], "path": "x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/schemas/conversations/bulk_crud_conversations_route.gen.ts", "deprecated": false, @@ -6676,7 +6676,7 @@ "label": "UpdateConversationRequestBody", "description": [], "signature": [ - "Zod.ZodObject<{ id: Zod.ZodEffects; title: Zod.ZodOptional; category: Zod.ZodOptional>; messages: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\">>>; role: Zod.ZodEnum<[\"system\", \"user\", \"assistant\"]>; timestamp: Zod.ZodEffects; isError: Zod.ZodOptional; traceData: Zod.ZodOptional; traceId: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { transactionId?: string | undefined; traceId?: string | undefined; }, { transactionId?: string | undefined; traceId?: string | undefined; }>>; }, \"strip\", Zod.ZodTypeAny, { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }, { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }>, \"many\">>; apiConfig: Zod.ZodOptional; provider: Zod.ZodOptional>; model: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; }, { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; }>>; summary: Zod.ZodOptional; timestamp: Zod.ZodOptional>; public: Zod.ZodOptional; confidence: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; }, { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; }>>; excludeFromLastConversationStorage: Zod.ZodOptional; replacements: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodString, \"strip\">>>; }, \"strip\", Zod.ZodTypeAny, { id: string; title?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }, { id: string; title?: string | undefined; category?: \"assistant\" | \"insights\" | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }>" + "Zod.ZodObject<{ id: Zod.ZodEffects; title: Zod.ZodOptional; category: Zod.ZodOptional>; messages: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\">>>; role: Zod.ZodEnum<[\"system\", \"user\", \"assistant\"]>; timestamp: Zod.ZodEffects; isError: Zod.ZodOptional; traceData: Zod.ZodOptional; traceId: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { transactionId?: string | undefined; traceId?: string | undefined; }, { transactionId?: string | undefined; traceId?: string | undefined; }>>; }, \"strip\", Zod.ZodTypeAny, { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }, { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }>, \"many\">>; apiConfig: Zod.ZodOptional; provider: Zod.ZodOptional>; model: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; }, { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; }>>; summary: Zod.ZodOptional; timestamp: Zod.ZodOptional>; public: Zod.ZodOptional; confidence: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; }, { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; }>>; excludeFromLastConversationStorage: Zod.ZodOptional; replacements: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodString, \"strip\">>>; }, \"strip\", Zod.ZodTypeAny, { id: string; title?: string | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }, { id: string; title?: string | undefined; summary?: { timestamp?: string | undefined; content?: string | undefined; public?: boolean | undefined; confidence?: \"medium\" | \"high\" | \"low\" | undefined; } | undefined; category?: \"assistant\" | \"insights\" | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; apiConfig?: { connectorId: string; actionTypeId: string; provider?: \"Other\" | \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; defaultSystemPromptId?: string | undefined; } | undefined; messages?: { timestamp: string; role: \"user\" | \"system\" | \"assistant\"; content: string; isError?: boolean | undefined; reader?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; traceData?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }[] | undefined; excludeFromLastConversationStorage?: boolean | undefined; }>" ], "path": "x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/schemas/conversations/crud_conversation_route.gen.ts", "deprecated": false, diff --git a/api_docs/kbn_elastic_assistant_common.mdx b/api_docs/kbn_elastic_assistant_common.mdx index fe6e1fe4afbb0..5db7c27142bea 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant-common'] --- import kbnElasticAssistantCommonObj from './kbn_elastic_assistant_common.devdocs.json'; diff --git a/api_docs/kbn_entities_schema.mdx b/api_docs/kbn_entities_schema.mdx index b0ea6f9dc878c..99a922195572c 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: 2025-01-16 +date: 2025-01-21 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 e221cad687f5e..d58494d1ff8d3 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: 2025-01-16 +date: 2025-01-21 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 b8a02d97fda54..aa39f1a665ca3 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: 2025-01-16 +date: 2025-01-21 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 904b7e951d1b3..4df8aadff37a9 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.devdocs.json b/api_docs/kbn_es_query.devdocs.json index 2156065788810..4340a4c216a29 100644 --- a/api_docs/kbn_es_query.devdocs.json +++ b/api_docs/kbn_es_query.devdocs.json @@ -1781,7 +1781,7 @@ "section": "def-common.RangeFilter", "text": "RangeFilter" }, - ") => { from: moment.Moment; to: moment.Moment; }" + ") => { from: string | moment.Moment; to: string | moment.Moment; }" ], "path": "src/platform/packages/shared/kbn-es-query/src/filters/helpers/convert_range_filter.ts", "deprecated": false, diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index 49c5d1b2e60c7..716bdee1a22f7 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: 2025-01-16 +date: 2025-01-21 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 acfd2f44a4cbd..f5b4976f91d21 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: 2025-01-16 +date: 2025-01-21 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 5e1310e2b6dec..4fc266dc32173 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: 2025-01-16 +date: 2025-01-21 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 208c08c03d8c6..41079d3debe32 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-ast'] --- import kbnEsqlAstObj from './kbn_esql_ast.devdocs.json'; diff --git a/api_docs/kbn_esql_editor.mdx b/api_docs/kbn_esql_editor.mdx index f9dc2b7178f0c..bd5f26991a297 100644 --- a/api_docs/kbn_esql_editor.mdx +++ b/api_docs/kbn_esql_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-editor title: "@kbn/esql-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-editor plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-editor'] --- import kbnEsqlEditorObj from './kbn_esql_editor.devdocs.json'; diff --git a/api_docs/kbn_esql_utils.mdx b/api_docs/kbn_esql_utils.mdx index 9fc091019aca7..916b444f257c4 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: 2025-01-16 +date: 2025-01-21 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 6bf51d8f262c2..6f3990f73e994 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: 2025-01-16 +date: 2025-01-21 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 b07d0e06e4724..1dbbb90b0a7f8 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: 2025-01-16 +date: 2025-01-21 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 d523f06ff2400..94961d6ef688b 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: 2025-01-16 +date: 2025-01-21 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 621af0d3d4756..903a6c9a83356 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: 2025-01-16 +date: 2025-01-21 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 2db8232a634be..499c3443be87c 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: 2025-01-16 +date: 2025-01-21 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 c7bd9d772e069..36613676dc761 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: 2025-01-16 +date: 2025-01-21 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 d23128add4b42..5a01a1f8dc5d8 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: 2025-01-16 +date: 2025-01-21 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_ftr_common_functional_services.devdocs.json b/api_docs/kbn_ftr_common_functional_services.devdocs.json index d7fea06c3d9c2..3f9be53dbd010 100644 --- a/api_docs/kbn_ftr_common_functional_services.devdocs.json +++ b/api_docs/kbn_ftr_common_functional_services.devdocs.json @@ -1185,6 +1185,68 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/ftr-common-functional-services", + "id": "def-common.retryForSuccess", + "type": "Function", + "tags": [], + "label": "retryForSuccess", + "description": [], + "signature": [ + "(log: ", + { + "pluginId": "@kbn/tooling-log", + "scope": "common", + "docId": "kibKbnToolingLogPluginApi", + "section": "def-common.ToolingLog", + "text": "ToolingLog" + }, + ", options: Options) => Promise" + ], + "path": "packages/kbn-ftr-common-functional-services/services/retry/retry_for_success.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-services", + "id": "def-common.retryForSuccess.$1", + "type": "Object", + "tags": [], + "label": "log", + "description": [], + "signature": [ + { + "pluginId": "@kbn/tooling-log", + "scope": "common", + "docId": "kibKbnToolingLogPluginApi", + "section": "def-common.ToolingLog", + "text": "ToolingLog" + } + ], + "path": "packages/kbn-ftr-common-functional-services/services/retry/retry_for_success.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-services", + "id": "def-common.retryForSuccess.$2", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "Options" + ], + "path": "packages/kbn-ftr-common-functional-services/services/retry/retry_for_success.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/ftr-common-functional-services", "id": "def-common.runSavedObjInfoSvc", diff --git a/api_docs/kbn_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index c2f1bf900dab6..29a2bac582ec3 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-services'] --- import kbnFtrCommonFunctionalServicesObj from './kbn_ftr_common_functional_services.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kiban | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 111 | 2 | 86 | 1 | +| 114 | 2 | 89 | 1 | ## Common diff --git a/api_docs/kbn_ftr_common_functional_ui_services.mdx b/api_docs/kbn_ftr_common_functional_ui_services.mdx index 0e6b3985c6d71..4b6a69728692b 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: 2025-01-16 +date: 2025-01-21 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_gen_ai_functional_testing.mdx b/api_docs/kbn_gen_ai_functional_testing.mdx index a5fedbb59c4b0..dd0c6e047ac11 100644 --- a/api_docs/kbn_gen_ai_functional_testing.mdx +++ b/api_docs/kbn_gen_ai_functional_testing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-gen-ai-functional-testing title: "@kbn/gen-ai-functional-testing" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/gen-ai-functional-testing plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/gen-ai-functional-testing'] --- import kbnGenAiFunctionalTestingObj from './kbn_gen_ai_functional_testing.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index 8f89c0ee7a447..fe29936649e2b 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: 2025-01-16 +date: 2025-01-21 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 8d75d97ae6ee2..fe419f484e40f 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: 2025-01-16 +date: 2025-01-21 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 6ab8cda16bb52..91e4437429414 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv'] --- import kbnGenerateCsvObj from './kbn_generate_csv.devdocs.json'; diff --git a/api_docs/kbn_grid_layout.mdx b/api_docs/kbn_grid_layout.mdx index e88d1a647d0b5..85c49e8cc8edc 100644 --- a/api_docs/kbn_grid_layout.mdx +++ b/api_docs/kbn_grid_layout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-grid-layout title: "@kbn/grid-layout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/grid-layout plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/grid-layout'] --- import kbnGridLayoutObj from './kbn_grid_layout.devdocs.json'; diff --git a/api_docs/kbn_grouping.mdx b/api_docs/kbn_grouping.mdx index 6dc315791f3c6..d76d611c1bf2e 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: 2025-01-16 +date: 2025-01-21 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 63ca935b4176b..7c8bb6e05c302 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: 2025-01-16 +date: 2025-01-21 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 6be574f23fd72..40e8d0abbd58a 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: 2025-01-16 +date: 2025-01-21 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 e8c453824676f..32137105a0443 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: 2025-01-16 +date: 2025-01-21 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 e3b19a171bae7..59abb50460fdc 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: 2025-01-16 +date: 2025-01-21 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 23d1f4ac5ca50..da4cee8e2344c 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: 2025-01-16 +date: 2025-01-21 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 4e68d0e7d68ff..8370637bba9f4 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: 2025-01-16 +date: 2025-01-21 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 455fc549575ae..7df566eeaf61f 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: 2025-01-16 +date: 2025-01-21 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 845b22c76b36a..1ea23bc8abe91 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: 2025-01-16 +date: 2025-01-21 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 072bbfe73fd22..9ac6e388cf1a5 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_index_adapter.mdx b/api_docs/kbn_index_adapter.mdx index 33f972979156a..fb3a724647011 100644 --- a/api_docs/kbn_index_adapter.mdx +++ b/api_docs/kbn_index_adapter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-index-adapter title: "@kbn/index-adapter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/index-adapter plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/index-adapter'] --- import kbnIndexAdapterObj from './kbn_index_adapter.devdocs.json'; diff --git a/api_docs/kbn_index_lifecycle_management_common_shared.mdx b/api_docs/kbn_index_lifecycle_management_common_shared.mdx index 1c55898edbb02..a6cd1f4f96c80 100644 --- a/api_docs/kbn_index_lifecycle_management_common_shared.mdx +++ b/api_docs/kbn_index_lifecycle_management_common_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-index-lifecycle-management-common-shared title: "@kbn/index-lifecycle-management-common-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/index-lifecycle-management-common-shared plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/index-lifecycle-management-common-shared'] --- import kbnIndexLifecycleManagementCommonSharedObj from './kbn_index_lifecycle_management_common_shared.devdocs.json'; diff --git a/api_docs/kbn_index_management_shared_types.mdx b/api_docs/kbn_index_management_shared_types.mdx index b813333e326c8..98af5c96c79b9 100644 --- a/api_docs/kbn_index_management_shared_types.mdx +++ b/api_docs/kbn_index_management_shared_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-index-management-shared-types title: "@kbn/index-management-shared-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/index-management-shared-types plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/index-management-shared-types'] --- import kbnIndexManagementSharedTypesObj from './kbn_index_management_shared_types.devdocs.json'; diff --git a/api_docs/kbn_inference_common.devdocs.json b/api_docs/kbn_inference_common.devdocs.json index 7d510051ce843..7527566d08638 100644 --- a/api_docs/kbn_inference_common.devdocs.json +++ b/api_docs/kbn_inference_common.devdocs.json @@ -1579,6 +1579,22 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "@kbn/inference-common", + "id": "def-common.OutputOptions.modelName", + "type": "string", + "tags": [], + "label": "modelName", + "description": [ + "\nThe model name identifier to use. Can be defined to use another model than the\ndefault one, when using connectors / providers exposing multiple models.\n\nDefaults to the default model as defined by the used connector." + ], + "signature": [ + "string | undefined" + ], + "path": "x-pack/platform/packages/shared/ai-infra/inference-common/src/output/api.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/inference-common", "id": "def-common.OutputOptions.functionCalling", @@ -2162,7 +2178,7 @@ "label": "options", "description": [], "signature": [ - "{ [P in \"abortSignal\" | \"temperature\" | \"system\" | \"stream\" | \"messages\" | Exclude]: ", + "{ [P in \"abortSignal\" | \"temperature\" | \"system\" | \"stream\" | \"messages\" | \"modelName\" | Exclude]: ", { "pluginId": "@kbn/inference-common", "scope": "common", @@ -2257,7 +2273,7 @@ "label": "options", "description": [], "signature": [ - "{ id: TId; abortSignal?: AbortSignal | undefined; input: string; schema?: TOutputSchema | undefined; retry?: { onValidationError?: number | boolean | undefined; } | undefined; system?: string | undefined; stream?: TStream | undefined; previousMessages?: ", + "{ id: TId; abortSignal?: AbortSignal | undefined; input: string; schema?: TOutputSchema | undefined; retry?: { onValidationError?: number | boolean | undefined; } | undefined; system?: string | undefined; stream?: TStream | undefined; modelName?: string | undefined; previousMessages?: ", { "pluginId": "@kbn/inference-common", "scope": "common", @@ -2364,7 +2380,7 @@ "section": "def-common.Message", "text": "Message" }, - "[]; temperature?: number | undefined; functionCalling?: ", + "[]; temperature?: number | undefined; modelName?: string | undefined; functionCalling?: ", { "pluginId": "@kbn/inference-common", "scope": "common", @@ -2432,7 +2448,7 @@ "section": "def-common.Message", "text": "Message" }, - "[]; temperature?: number | undefined; functionCalling?: ", + "[]; temperature?: number | undefined; modelName?: string | undefined; functionCalling?: ", { "pluginId": "@kbn/inference-common", "scope": "common", @@ -3455,7 +3471,7 @@ "\nOptions used to call the {@link BoundChatCompleteAPI}" ], "signature": [ - "{ [P in \"abortSignal\" | \"temperature\" | \"system\" | \"stream\" | \"messages\" | Exclude]: ", + "{ [P in \"abortSignal\" | \"temperature\" | \"system\" | \"stream\" | \"messages\" | \"modelName\" | Exclude]: ", { "pluginId": "@kbn/inference-common", "scope": "common", @@ -3480,7 +3496,7 @@ "\nOptions used to call the {@link BoundOutputAPI}" ], "signature": [ - "{ id: TId; abortSignal?: AbortSignal | undefined; input: string; schema?: TOutputSchema | undefined; retry?: { onValidationError?: number | boolean | undefined; } | undefined; system?: string | undefined; stream?: TStream | undefined; previousMessages?: ", + "{ id: TId; abortSignal?: AbortSignal | undefined; input: string; schema?: TOutputSchema | undefined; retry?: { onValidationError?: number | boolean | undefined; } | undefined; system?: string | undefined; stream?: TStream | undefined; modelName?: string | undefined; previousMessages?: ", { "pluginId": "@kbn/inference-common", "scope": "common", diff --git a/api_docs/kbn_inference_common.mdx b/api_docs/kbn_inference_common.mdx index 54efd5217eaaf..7664930b59ea0 100644 --- a/api_docs/kbn_inference_common.mdx +++ b/api_docs/kbn_inference_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-inference-common title: "@kbn/inference-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/inference-common plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/inference-common'] --- import kbnInferenceCommonObj from './kbn_inference_common.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/appex-ai-infra](https://github.com/orgs/elastic/teams/appex-ai | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 160 | 0 | 55 | 4 | +| 161 | 0 | 55 | 4 | ## Common diff --git a/api_docs/kbn_inference_endpoint_ui_common.mdx b/api_docs/kbn_inference_endpoint_ui_common.mdx index ffe592949ef49..8e3e4a6d3495d 100644 --- a/api_docs/kbn_inference_endpoint_ui_common.mdx +++ b/api_docs/kbn_inference_endpoint_ui_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-inference-endpoint-ui-common title: "@kbn/inference-endpoint-ui-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/inference-endpoint-ui-common plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/inference-endpoint-ui-common'] --- import kbnInferenceEndpointUiCommonObj from './kbn_inference_endpoint_ui_common.devdocs.json'; diff --git a/api_docs/kbn_inference_integration_flyout.mdx b/api_docs/kbn_inference_integration_flyout.mdx index 52f4aa43d0836..53b3352fe8c30 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: 2025-01-16 +date: 2025-01-21 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 e9bfa8de70b95..194dfaf1a8642 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: 2025-01-16 +date: 2025-01-21 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 c15692fd1f313..a09e8533e3dd8 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_investigation_shared.mdx b/api_docs/kbn_investigation_shared.mdx index 674f20a904252..cfb8d078c0919 100644 --- a/api_docs/kbn_investigation_shared.mdx +++ b/api_docs/kbn_investigation_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-investigation-shared title: "@kbn/investigation-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/investigation-shared plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/investigation-shared'] --- import kbnInvestigationSharedObj from './kbn_investigation_shared.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 8b5d7721dfb9b..a2e41dd72af3b 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: 2025-01-16 +date: 2025-01-21 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 c0442fc99902e..88230b430cdfe 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ipynb'] --- import kbnIpynbObj from './kbn_ipynb.devdocs.json'; diff --git a/api_docs/kbn_item_buffer.mdx b/api_docs/kbn_item_buffer.mdx index ebadc405357ec..4e139317e6645 100644 --- a/api_docs/kbn_item_buffer.mdx +++ b/api_docs/kbn_item_buffer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-item-buffer title: "@kbn/item-buffer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/item-buffer plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/item-buffer'] --- import kbnItemBufferObj from './kbn_item_buffer.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index 94ea76387f20f..1d27bdb33ffb6 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: 2025-01-16 +date: 2025-01-21 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 81c6d72e66882..7209934b2e7c2 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: 2025-01-16 +date: 2025-01-21 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 defcc8339635b..12e60cfe2e311 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: 2025-01-16 +date: 2025-01-21 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 94ce5115f6a80..43e8d5ca229ef 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: 2025-01-16 +date: 2025-01-21 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 7d5d75892a498..7ac854369ae26 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: 2025-01-16 +date: 2025-01-21 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.mdx b/api_docs/kbn_language_documentation.mdx index cfb5ca5a6b264..5125474e677b6 100644 --- a/api_docs/kbn_language_documentation.mdx +++ b/api_docs/kbn_language_documentation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-language-documentation title: "@kbn/language-documentation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/language-documentation plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation'] --- import kbnLanguageDocumentationObj from './kbn_language_documentation.devdocs.json'; diff --git a/api_docs/kbn_lens_embeddable_utils.mdx b/api_docs/kbn_lens_embeddable_utils.mdx index 33ccd8b84df26..8765220d242f4 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: 2025-01-16 +date: 2025-01-21 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 85f82864513cf..7bfadca8d37b4 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: 2025-01-16 +date: 2025-01-21 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 e73118b5dd9db..328863d0597a1 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: 2025-01-16 +date: 2025-01-21 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 9fcda1fd72286..980b0138027f1 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: 2025-01-16 +date: 2025-01-21 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 df92e486cdb57..8ed445ea748c5 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: 2025-01-16 +date: 2025-01-21 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 d354db1e26d8c..30516ce174e11 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: 2025-01-16 +date: 2025-01-21 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 e6c9cafb89078..d00ed6a10d961 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: 2025-01-16 +date: 2025-01-21 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 add908233f40d..b2db4cabdfec0 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: 2025-01-16 +date: 2025-01-21 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 cb8a9424eee56..5a46c06bc48da 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: 2025-01-16 +date: 2025-01-21 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 ee7ec1316eed7..1a0f7041f4ec9 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: 2025-01-16 +date: 2025-01-21 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 a7888717d65e7..bfe866d99d15e 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: 2025-01-16 +date: 2025-01-21 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 ddbefa536f58b..7443c057b5344 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: 2025-01-16 +date: 2025-01-21 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 104a30efbfcdc..7a5102eebbfe0 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: 2025-01-16 +date: 2025-01-21 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 91de47d529904..5f00f88b7796e 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: 2025-01-16 +date: 2025-01-21 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 3d6f9dbf1568b..945aea75fd411 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: 2025-01-16 +date: 2025-01-21 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 2534e0666a5a1..30b55bfb9e4b1 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: 2025-01-16 +date: 2025-01-21 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 ddfb27c498088..796c1b1ce54af 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: 2025-01-16 +date: 2025-01-21 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 ae9ad2b5fa89b..8edb57e7b19c3 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-storybook-config'] --- import kbnManagementStorybookConfigObj from './kbn_management_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_manifest.mdx b/api_docs/kbn_manifest.mdx index 2c187492eff5c..6c2015dc0b3b5 100644 --- a/api_docs/kbn_manifest.mdx +++ b/api_docs/kbn_manifest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-manifest title: "@kbn/manifest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/manifest plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/manifest'] --- import kbnManifestObj from './kbn_manifest.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index ec709a4902109..fb7715fb87860 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: 2025-01-16 +date: 2025-01-21 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 fb5cb3f8ed515..e320f2834d0aa 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: 2025-01-16 +date: 2025-01-21 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 76386cb85b33c..fc87b2260bd89 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: 2025-01-16 +date: 2025-01-21 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 09517c455ffbb..aa1ccb09646fa 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: 2025-01-16 +date: 2025-01-21 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 4af535d1db67f..7061c7cb5e9f7 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: 2025-01-16 +date: 2025-01-21 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 8db9e98cde443..f257824f900c3 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: 2025-01-16 +date: 2025-01-21 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 80bd7fdb238f3..90744c7021c89 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: 2025-01-16 +date: 2025-01-21 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 0329aa188bfc4..bf1e56eae1bc5 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: 2025-01-16 +date: 2025-01-21 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 aa8e0b0090f2e..facbbfb3abce9 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: 2025-01-16 +date: 2025-01-21 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 fa078dbeecdc0..e17543ef0022f 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: 2025-01-16 +date: 2025-01-21 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 bb85898c5b44a..56824dd7ed581 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: 2025-01-16 +date: 2025-01-21 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 88a8f729d04e0..b8401736abc4b 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: 2025-01-16 +date: 2025-01-21 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_field_stats_flyout.mdx b/api_docs/kbn_ml_field_stats_flyout.mdx index b18b2f72e3ba4..adaad80ea7ae6 100644 --- a/api_docs/kbn_ml_field_stats_flyout.mdx +++ b/api_docs/kbn_ml_field_stats_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-field-stats-flyout title: "@kbn/ml-field-stats-flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-field-stats-flyout plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-field-stats-flyout'] --- import kbnMlFieldStatsFlyoutObj from './kbn_ml_field_stats_flyout.devdocs.json'; diff --git a/api_docs/kbn_ml_in_memory_table.mdx b/api_docs/kbn_ml_in_memory_table.mdx index 2f992795a4fb7..6b2b8b92a3562 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: 2025-01-16 +date: 2025-01-21 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 cf2025ff8e026..a99a6267497bd 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: 2025-01-16 +date: 2025-01-21 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 126bddeffd392..552c438739c84 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: 2025-01-16 +date: 2025-01-21 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_local_storage.mdx b/api_docs/kbn_ml_local_storage.mdx index a16b63f3c0e84..c6178d633046b 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: 2025-01-16 +date: 2025-01-21 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 0d74062cda5cb..efe3cfddc23a7 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: 2025-01-16 +date: 2025-01-21 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 976720a09e702..795f6647fd8de 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: 2025-01-16 +date: 2025-01-21 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_parse_interval.mdx b/api_docs/kbn_ml_parse_interval.mdx index 1f86b3820d4ea..1cce30ea11d4a 100644 --- a/api_docs/kbn_ml_parse_interval.mdx +++ b/api_docs/kbn_ml_parse_interval.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-parse-interval title: "@kbn/ml-parse-interval" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-parse-interval plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-parse-interval'] --- import kbnMlParseIntervalObj from './kbn_ml_parse_interval.devdocs.json'; diff --git a/api_docs/kbn_ml_query_utils.mdx b/api_docs/kbn_ml_query_utils.mdx index 05fe2876aba32..f70c036ddd4fe 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: 2025-01-16 +date: 2025-01-21 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 e0c3a1187b7aa..76cc88ef76a30 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: 2025-01-16 +date: 2025-01-21 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 c2d4addb4096b..cb7e6b8265bc3 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: 2025-01-16 +date: 2025-01-21 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 a9ccf1fe129cc..f6ed27b0bc237 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: 2025-01-16 +date: 2025-01-21 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 95cf649a9e1ce..90f3b654cad43 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: 2025-01-16 +date: 2025-01-21 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 cab1b3a105b07..f104417ac8ddc 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: 2025-01-16 +date: 2025-01-21 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 4e768d3083c1a..c3b98ec4306de 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: 2025-01-16 +date: 2025-01-21 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 a54932c89d906..fa7e76a5a73ac 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: 2025-01-16 +date: 2025-01-21 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 61f40051af3b8..8a462e7ce9ed5 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_ml_validators.mdx b/api_docs/kbn_ml_validators.mdx index 15df1c0812737..671d575f9970b 100644 --- a/api_docs/kbn_ml_validators.mdx +++ b/api_docs/kbn_ml_validators.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-validators title: "@kbn/ml-validators" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-validators plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-validators'] --- import kbnMlValidatorsObj from './kbn_ml_validators.devdocs.json'; diff --git a/api_docs/kbn_mock_idp_utils.mdx b/api_docs/kbn_mock_idp_utils.mdx index ffb5883a62983..92d6d97edd7e9 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: 2025-01-16 +date: 2025-01-21 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 0cb759c4496a6..14b8c2e586889 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_object_utils.mdx b/api_docs/kbn_object_utils.mdx index af8a7dc9167de..9abbe61008099 100644 --- a/api_docs/kbn_object_utils.mdx +++ b/api_docs/kbn_object_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-object-utils title: "@kbn/object-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/object-utils plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/object-utils'] --- import kbnObjectUtilsObj from './kbn_object_utils.devdocs.json'; diff --git a/api_docs/kbn_object_versioning.mdx b/api_docs/kbn_object_versioning.mdx index ee06de37fd57d..255c8f04803a8 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/object-versioning'] --- import kbnObjectVersioningObj from './kbn_object_versioning.devdocs.json'; diff --git a/api_docs/kbn_object_versioning_utils.mdx b/api_docs/kbn_object_versioning_utils.mdx index 8bde8b23ad82d..eac772b51f8cf 100644 --- a/api_docs/kbn_object_versioning_utils.mdx +++ b/api_docs/kbn_object_versioning_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-object-versioning-utils title: "@kbn/object-versioning-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/object-versioning-utils plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/object-versioning-utils'] --- import kbnObjectVersioningUtilsObj from './kbn_object_versioning_utils.devdocs.json'; diff --git a/api_docs/kbn_observability_alert_details.mdx b/api_docs/kbn_observability_alert_details.mdx index b7c4d4397c7eb..e62be78b4d368 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: 2025-01-16 +date: 2025-01-21 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_rule_utils.mdx b/api_docs/kbn_observability_alerting_rule_utils.mdx index a075291755681..97d453423acfd 100644 --- a/api_docs/kbn_observability_alerting_rule_utils.mdx +++ b/api_docs/kbn_observability_alerting_rule_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alerting-rule-utils title: "@kbn/observability-alerting-rule-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alerting-rule-utils plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alerting-rule-utils'] --- import kbnObservabilityAlertingRuleUtilsObj from './kbn_observability_alerting_rule_utils.devdocs.json'; diff --git a/api_docs/kbn_observability_alerting_test_data.mdx b/api_docs/kbn_observability_alerting_test_data.mdx index 0752a45d15907..d8d73a214485f 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: 2025-01-16 +date: 2025-01-21 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 9f20649fec04c..a1973b309a108 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: 2025-01-16 +date: 2025-01-21 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_observability_logs_overview.mdx b/api_docs/kbn_observability_logs_overview.mdx index 58f8e97dce6b7..f963a1e5044d3 100644 --- a/api_docs/kbn_observability_logs_overview.mdx +++ b/api_docs/kbn_observability_logs_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-logs-overview title: "@kbn/observability-logs-overview" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-logs-overview plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-logs-overview'] --- import kbnObservabilityLogsOverviewObj from './kbn_observability_logs_overview.devdocs.json'; diff --git a/api_docs/kbn_observability_synthetics_test_data.mdx b/api_docs/kbn_observability_synthetics_test_data.mdx index 95baa510e5090..a08ec24fd2e8e 100644 --- a/api_docs/kbn_observability_synthetics_test_data.mdx +++ b/api_docs/kbn_observability_synthetics_test_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-synthetics-test-data title: "@kbn/observability-synthetics-test-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-synthetics-test-data plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-synthetics-test-data'] --- import kbnObservabilitySyntheticsTestDataObj from './kbn_observability_synthetics_test_data.devdocs.json'; diff --git a/api_docs/kbn_openapi_bundler.mdx b/api_docs/kbn_openapi_bundler.mdx index 371b2c24d886d..bd13dce043246 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: 2025-01-16 +date: 2025-01-21 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 7dd97a4dd0a93..8c59bd2802f06 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: 2025-01-16 +date: 2025-01-21 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 5043899b947b6..fb6a1d5228fee 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: 2025-01-16 +date: 2025-01-21 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 41b3b17befd17..f7ca41bccae04 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: 2025-01-16 +date: 2025-01-21 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 f75f0a4f115d5..8d18cbe3c6cff 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: 2025-01-16 +date: 2025-01-21 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_palettes.mdx b/api_docs/kbn_palettes.mdx index 4f51cc8de539d..fcb1b04f7105c 100644 --- a/api_docs/kbn_palettes.mdx +++ b/api_docs/kbn_palettes.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-palettes title: "@kbn/palettes" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/palettes plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/palettes'] --- import kbnPalettesObj from './kbn_palettes.devdocs.json'; diff --git a/api_docs/kbn_panel_loader.mdx b/api_docs/kbn_panel_loader.mdx index a421ce25bd992..06df8e146c091 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: 2025-01-16 +date: 2025-01-21 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 fec808c688988..77c75e38ac925 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: 2025-01-16 +date: 2025-01-21 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 a1e2d64342ef1..046c1ffccbd81 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: 2025-01-16 +date: 2025-01-21 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 e027b43ad611f..56e5d6a15f9d4 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: 2025-01-16 +date: 2025-01-21 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 93ac56e53b134..5302a6d85acb9 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: 2025-01-16 +date: 2025-01-21 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 fa4637cc27e47..c30383679bcfd 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: 2025-01-16 +date: 2025-01-21 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 e0b2fff44838f..00fac2593be4a 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/presentation-publishing'] --- import kbnPresentationPublishingObj from './kbn_presentation_publishing.devdocs.json'; diff --git a/api_docs/kbn_product_doc_artifact_builder.mdx b/api_docs/kbn_product_doc_artifact_builder.mdx index 9c6ebf7cda612..b48adf7d2c32a 100644 --- a/api_docs/kbn_product_doc_artifact_builder.mdx +++ b/api_docs/kbn_product_doc_artifact_builder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-product-doc-artifact-builder title: "@kbn/product-doc-artifact-builder" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/product-doc-artifact-builder plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/product-doc-artifact-builder'] --- import kbnProductDocArtifactBuilderObj from './kbn_product_doc_artifact_builder.devdocs.json'; diff --git a/api_docs/kbn_product_doc_common.mdx b/api_docs/kbn_product_doc_common.mdx index 25666fcdbc4aa..43799df636df3 100644 --- a/api_docs/kbn_product_doc_common.mdx +++ b/api_docs/kbn_product_doc_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-product-doc-common title: "@kbn/product-doc-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/product-doc-common plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/product-doc-common'] --- import kbnProductDocCommonObj from './kbn_product_doc_common.devdocs.json'; diff --git a/api_docs/kbn_profiling_utils.mdx b/api_docs/kbn_profiling_utils.mdx index 3c04fcaec0ddc..01e76e189e4c3 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: 2025-01-16 +date: 2025-01-21 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 ae24050659a23..e7df5aa498203 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/random-sampling'] --- import kbnRandomSamplingObj from './kbn_random_sampling.devdocs.json'; diff --git a/api_docs/kbn_react_field.devdocs.json b/api_docs/kbn_react_field.devdocs.json index 3e95b8ee4b828..abb55efb0d304 100644 --- a/api_docs/kbn_react_field.devdocs.json +++ b/api_docs/kbn_react_field.devdocs.json @@ -363,10 +363,13 @@ { "parentPluginId": "@kbn/react-field", "id": "def-common.FieldIconProps.type", - "type": "string", + "type": "CompoundType", "tags": [], "label": "type", "description": [], + "signature": [ + "\"string\" | \"number\" | \"boolean\" | \"nested\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"version\" | \"murmur3\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"scaled_float\" | \"double\" | \"date_range\" | \"ip_range\" | \"rank_feature\" | \"rank_features\" | \"flattened\" | \"shape\" | \"histogram\" | \"dense_vector\" | \"semantic_text\" | \"sparse_vector\" | \"match_only_text\" | \"conflict\" | \"point\" | \"unsigned_long\" | \"_source\" | (string & {}) | \"gauge\" | \"counter\" | \"number_range\"" + ], "path": "src/platform/packages/shared/kbn-react-field/src/field_icon/field_icon.tsx", "deprecated": false, "trackAdoption": false diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index 6ccab9e58b7a6..5d91a050adc1f 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: 2025-01-16 +date: 2025-01-21 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 8278c994c25e3..d50586cb356ba 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: 2025-01-16 +date: 2025-01-21 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 136a11e050fc4..d5dde0fc6fca1 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: 2025-01-16 +date: 2025-01-21 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 99b69beec1c0b..93788c516c2a3 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: 2025-01-16 +date: 2025-01-21 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 9965eb97214e2..2917127d7b204 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: 2025-01-16 +date: 2025-01-21 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 e274c9ff23e56..64d9cde0ef4b0 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: 2025-01-16 +date: 2025-01-21 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 32dfb06aba460..4c45c64e407db 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: 2025-01-16 +date: 2025-01-21 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 50e4248522dfa..ed4e2cac565a9 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-mount'] --- import kbnReactKibanaMountObj from './kbn_react_kibana_mount.devdocs.json'; diff --git a/api_docs/kbn_react_mute_legacy_root_warning.mdx b/api_docs/kbn_react_mute_legacy_root_warning.mdx index 9af407dfaee44..3414235ad073d 100644 --- a/api_docs/kbn_react_mute_legacy_root_warning.mdx +++ b/api_docs/kbn_react_mute_legacy_root_warning.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-mute-legacy-root-warning title: "@kbn/react-mute-legacy-root-warning" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-mute-legacy-root-warning plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-mute-legacy-root-warning'] --- import kbnReactMuteLegacyRootWarningObj from './kbn_react_mute_legacy_root_warning.devdocs.json'; diff --git a/api_docs/kbn_recently_accessed.mdx b/api_docs/kbn_recently_accessed.mdx index d12056a070495..bf7a783767932 100644 --- a/api_docs/kbn_recently_accessed.mdx +++ b/api_docs/kbn_recently_accessed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-recently-accessed title: "@kbn/recently-accessed" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/recently-accessed plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/recently-accessed'] --- import kbnRecentlyAccessedObj from './kbn_recently_accessed.devdocs.json'; diff --git a/api_docs/kbn_relocate.mdx b/api_docs/kbn_relocate.mdx index 875c4ba946d0c..009114d1841c0 100644 --- a/api_docs/kbn_relocate.mdx +++ b/api_docs/kbn_relocate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-relocate title: "@kbn/relocate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/relocate plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/relocate'] --- import kbnRelocateObj from './kbn_relocate.devdocs.json'; diff --git a/api_docs/kbn_repo_file_maps.mdx b/api_docs/kbn_repo_file_maps.mdx index f9f771ce5b837..9826867c3baef 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: 2025-01-16 +date: 2025-01-21 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 f7db821ceaabb..e6da3d2ea3a2c 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: 2025-01-16 +date: 2025-01-21 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 7cf89451dc52b..ae9696a3004d9 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: 2025-01-16 +date: 2025-01-21 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 44e62260109aa..58c2fbcc492ae 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: 2025-01-16 +date: 2025-01-21 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 4a070cbf5e827..714b216508143 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: 2025-01-16 +date: 2025-01-21 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 25356230d5fcf..e8290cc3eea29 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: 2025-01-16 +date: 2025-01-21 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 38032a0d53b3e..016759cbc3439 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: 2025-01-16 +date: 2025-01-21 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 481e27bacd300..ffba82eb9447a 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: 2025-01-16 +date: 2025-01-21 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 23727adbcf82a..b7209e84887d6 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: 2025-01-16 +date: 2025-01-21 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 3e502d7365607..69cbd58737145 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: 2025-01-16 +date: 2025-01-21 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 dff7a2a23be06..96aece4ac78c9 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: 2025-01-16 +date: 2025-01-21 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 645ab027035a3..18a1057e48a0d 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: 2025-01-16 +date: 2025-01-21 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 427d9278ab23c..8423be7e371b5 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: 2025-01-16 +date: 2025-01-21 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 921a0f125d0db..72ebbbed8e6fa 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: 2025-01-16 +date: 2025-01-21 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 e4f823c8eac47..af34870420dfa 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: 2025-01-16 +date: 2025-01-21 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 3e84073660a69..1f3762474e75a 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/resizable-layout'] --- import kbnResizableLayoutObj from './kbn_resizable_layout.devdocs.json'; diff --git a/api_docs/kbn_response_ops_rule_form.mdx b/api_docs/kbn_response_ops_rule_form.mdx index 03fb0bccfb6cc..d11dde18c3dea 100644 --- a/api_docs/kbn_response_ops_rule_form.mdx +++ b/api_docs/kbn_response_ops_rule_form.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-response-ops-rule-form title: "@kbn/response-ops-rule-form" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/response-ops-rule-form plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/response-ops-rule-form'] --- import kbnResponseOpsRuleFormObj from './kbn_response_ops_rule_form.devdocs.json'; diff --git a/api_docs/kbn_response_ops_rule_params.mdx b/api_docs/kbn_response_ops_rule_params.mdx index 40417cba5b4cd..0112b1dbeb84f 100644 --- a/api_docs/kbn_response_ops_rule_params.mdx +++ b/api_docs/kbn_response_ops_rule_params.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-response-ops-rule-params title: "@kbn/response-ops-rule-params" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/response-ops-rule-params plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/response-ops-rule-params'] --- import kbnResponseOpsRuleParamsObj from './kbn_response_ops_rule_params.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index abbd9d9694c28..2f1d010d13623 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: 2025-01-16 +date: 2025-01-21 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 d2f9897393fde..40caf23529373 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: 2025-01-16 +date: 2025-01-21 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 4f9c14b48de94..12a23c2144529 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: 2025-01-16 +date: 2025-01-21 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 cc5ff0004d8f5..935d6c20c34ea 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: 2025-01-16 +date: 2025-01-21 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 4de6fd68df892..cde4110778415 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: 2025-01-16 +date: 2025-01-21 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 73d34cfd9c931..ebd0acb30a25d 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: 2025-01-16 +date: 2025-01-21 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 3a743fcba2c1d..f7a162459036e 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/saved-objects-settings'] --- import kbnSavedObjectsSettingsObj from './kbn_saved_objects_settings.devdocs.json'; diff --git a/api_docs/kbn_saved_search_component.mdx b/api_docs/kbn_saved_search_component.mdx index 09bda575f3f20..f6bea5f4c4e2b 100644 --- a/api_docs/kbn_saved_search_component.mdx +++ b/api_docs/kbn_saved_search_component.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-saved-search-component title: "@kbn/saved-search-component" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/saved-search-component plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/saved-search-component'] --- import kbnSavedSearchComponentObj from './kbn_saved_search_component.devdocs.json'; diff --git a/api_docs/kbn_scout.mdx b/api_docs/kbn_scout.mdx index 822233071ffc6..fa68012aee055 100644 --- a/api_docs/kbn_scout.mdx +++ b/api_docs/kbn_scout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-scout title: "@kbn/scout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/scout plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/scout'] --- import kbnScoutObj from './kbn_scout.devdocs.json'; diff --git a/api_docs/kbn_scout_info.mdx b/api_docs/kbn_scout_info.mdx index 2d53ef192cbf1..afd5d6f44b632 100644 --- a/api_docs/kbn_scout_info.mdx +++ b/api_docs/kbn_scout_info.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-scout-info title: "@kbn/scout-info" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/scout-info plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/scout-info'] --- import kbnScoutInfoObj from './kbn_scout_info.devdocs.json'; diff --git a/api_docs/kbn_scout_reporting.mdx b/api_docs/kbn_scout_reporting.mdx index a9c942e11aa1c..bf3df9716658a 100644 --- a/api_docs/kbn_scout_reporting.mdx +++ b/api_docs/kbn_scout_reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-scout-reporting title: "@kbn/scout-reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/scout-reporting plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/scout-reporting'] --- import kbnScoutReportingObj from './kbn_scout_reporting.devdocs.json'; diff --git a/api_docs/kbn_screenshotting_server.mdx b/api_docs/kbn_screenshotting_server.mdx index c5aa673998476..ec4aa8c621900 100644 --- a/api_docs/kbn_screenshotting_server.mdx +++ b/api_docs/kbn_screenshotting_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-screenshotting-server title: "@kbn/screenshotting-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/screenshotting-server plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/screenshotting-server'] --- import kbnScreenshottingServerObj from './kbn_screenshotting_server.devdocs.json'; diff --git a/api_docs/kbn_search_api_keys_components.mdx b/api_docs/kbn_search_api_keys_components.mdx index caa206248a253..5f5bc6b071348 100644 --- a/api_docs/kbn_search_api_keys_components.mdx +++ b/api_docs/kbn_search_api_keys_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-api-keys-components title: "@kbn/search-api-keys-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-api-keys-components plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-api-keys-components'] --- import kbnSearchApiKeysComponentsObj from './kbn_search_api_keys_components.devdocs.json'; diff --git a/api_docs/kbn_search_api_keys_server.mdx b/api_docs/kbn_search_api_keys_server.mdx index 34723cdaaf0a5..91916a31a2c55 100644 --- a/api_docs/kbn_search_api_keys_server.mdx +++ b/api_docs/kbn_search_api_keys_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-api-keys-server title: "@kbn/search-api-keys-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-api-keys-server plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-api-keys-server'] --- import kbnSearchApiKeysServerObj from './kbn_search_api_keys_server.devdocs.json'; diff --git a/api_docs/kbn_search_api_panels.mdx b/api_docs/kbn_search_api_panels.mdx index 523bb35a33480..808601d538356 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: 2025-01-16 +date: 2025-01-21 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.devdocs.json b/api_docs/kbn_search_connectors.devdocs.json index a04a1f458bd24..58f3cc4f18a4d 100644 --- a/api_docs/kbn_search_connectors.devdocs.json +++ b/api_docs/kbn_search_connectors.devdocs.json @@ -893,7 +893,7 @@ "signature": [ "(client: ", "ElasticsearchClient", - ", indexNames?: string[] | undefined, fetchOnlyCrawlers?: boolean | undefined, searchQuery?: string | undefined) => Promise<", + ", indexNames?: string[] | undefined, fetchOnlyCrawlers?: boolean | undefined, searchQuery?: string | undefined, includeDeleted?: boolean | undefined) => Promise<", { "pluginId": "@kbn/search-connectors", "scope": "common", @@ -966,6 +966,21 @@ "deprecated": false, "trackAdoption": false, "isRequired": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.fetchConnectors.$5", + "type": "CompoundType", + "tags": [], + "label": "includeDeleted", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/platform/packages/shared/kbn-search-connectors/lib/fetch_connectors.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false } ], "returnComment": [], @@ -3051,6 +3066,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.Connector.deleted", + "type": "CompoundType", + "tags": [], + "label": "deleted", + "description": [], + "signature": [ + "boolean | null" + ], + "path": "src/platform/packages/shared/kbn-search-connectors/types/connectors.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/search-connectors", "id": "def-common.Connector.language", @@ -6587,7 +6616,7 @@ "section": "def-common.ConnectorConfiguration", "text": "ConnectorConfiguration" }, - "; index_name: string | null; api_key_id: string | null; api_key_secret_id: string | null; custom_scheduling: ", + "; index_name: string | null; deleted: boolean | null; api_key_id: string | null; api_key_secret_id: string | null; custom_scheduling: ", { "pluginId": "@kbn/search-connectors", "scope": "common", diff --git a/api_docs/kbn_search_connectors.mdx b/api_docs/kbn_search_connectors.mdx index d5833f7efe805..44c0369d976a0 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-connectors'] --- import kbnSearchConnectorsObj from './kbn_search_connectors.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-ki | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3954 | 0 | 3954 | 0 | +| 3956 | 0 | 3956 | 0 | ## Common diff --git a/api_docs/kbn_search_errors.mdx b/api_docs/kbn_search_errors.mdx index 80e035f4fd664..00531937886e5 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: 2025-01-16 +date: 2025-01-21 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 ea9838a71e91c..178851496e139 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: 2025-01-16 +date: 2025-01-21 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 2441ebbb06571..7246c77b95ea6 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: 2025-01-16 +date: 2025-01-21 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_shared_ui.mdx b/api_docs/kbn_search_shared_ui.mdx index 7fc93b52d7d52..0cfca54dfa17c 100644 --- a/api_docs/kbn_search_shared_ui.mdx +++ b/api_docs/kbn_search_shared_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-shared-ui title: "@kbn/search-shared-ui" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-shared-ui plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-shared-ui'] --- import kbnSearchSharedUiObj from './kbn_search_shared_ui.devdocs.json'; diff --git a/api_docs/kbn_search_types.mdx b/api_docs/kbn_search_types.mdx index b0b5dd1564d70..44c75b97c79ef 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: 2025-01-16 +date: 2025-01-21 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.mdx b/api_docs/kbn_security_api_key_management.mdx index 9c0b07500ad48..df1b698cdc7d1 100644 --- a/api_docs/kbn_security_api_key_management.mdx +++ b/api_docs/kbn_security_api_key_management.mdx @@ -8,7 +8,7 @@ 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-api-key-management'] --- import kbnSecurityApiKeyManagementObj from './kbn_security_api_key_management.devdocs.json'; diff --git a/api_docs/kbn_security_authorization_core.mdx b/api_docs/kbn_security_authorization_core.mdx index 37e52b691c221..c7e6cee81362b 100644 --- a/api_docs/kbn_security_authorization_core.mdx +++ b/api_docs/kbn_security_authorization_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-authorization-core title: "@kbn/security-authorization-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-authorization-core plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-authorization-core'] --- import kbnSecurityAuthorizationCoreObj from './kbn_security_authorization_core.devdocs.json'; diff --git a/api_docs/kbn_security_authorization_core_common.mdx b/api_docs/kbn_security_authorization_core_common.mdx index 661623e7fbcc2..880fad19fd489 100644 --- a/api_docs/kbn_security_authorization_core_common.mdx +++ b/api_docs/kbn_security_authorization_core_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-authorization-core-common title: "@kbn/security-authorization-core-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-authorization-core-common plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-authorization-core-common'] --- import kbnSecurityAuthorizationCoreCommonObj from './kbn_security_authorization_core_common.devdocs.json'; diff --git a/api_docs/kbn_security_form_components.mdx b/api_docs/kbn_security_form_components.mdx index 188a09076b8f9..4a32b4ea0875c 100644 --- a/api_docs/kbn_security_form_components.mdx +++ b/api_docs/kbn_security_form_components.mdx @@ -8,7 +8,7 @@ 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-form-components'] --- import kbnSecurityFormComponentsObj from './kbn_security_form_components.devdocs.json'; diff --git a/api_docs/kbn_security_hardening.mdx b/api_docs/kbn_security_hardening.mdx index 3e77d02e6c1de..0f121b2a22aac 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: 2025-01-16 +date: 2025-01-21 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.mdx b/api_docs/kbn_security_plugin_types_common.mdx index ed203b74d7729..40f9a4164d387 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-common'] --- import kbnSecurityPluginTypesCommonObj from './kbn_security_plugin_types_common.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_public.mdx b/api_docs/kbn_security_plugin_types_public.mdx index 322ebcf5722f2..8bcce9120f45f 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: 2025-01-16 +date: 2025-01-21 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.mdx b/api_docs/kbn_security_plugin_types_server.mdx index 7e62513990844..260467dfa2db8 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-server'] --- import kbnSecurityPluginTypesServerObj from './kbn_security_plugin_types_server.devdocs.json'; diff --git a/api_docs/kbn_security_role_management_model.mdx b/api_docs/kbn_security_role_management_model.mdx index 5386c393f51b5..6c49a334268f0 100644 --- a/api_docs/kbn_security_role_management_model.mdx +++ b/api_docs/kbn_security_role_management_model.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-role-management-model title: "@kbn/security-role-management-model" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-role-management-model plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-role-management-model'] --- import kbnSecurityRoleManagementModelObj from './kbn_security_role_management_model.devdocs.json'; diff --git a/api_docs/kbn_security_solution_distribution_bar.mdx b/api_docs/kbn_security_solution_distribution_bar.mdx index 978a63c8ec0a5..a1c543dd9f427 100644 --- a/api_docs/kbn_security_solution_distribution_bar.mdx +++ b/api_docs/kbn_security_solution_distribution_bar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-distribution-bar title: "@kbn/security-solution-distribution-bar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-distribution-bar plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-distribution-bar'] --- import kbnSecuritySolutionDistributionBarObj from './kbn_security_solution_distribution_bar.devdocs.json'; diff --git a/api_docs/kbn_security_solution_features.devdocs.json b/api_docs/kbn_security_solution_features.devdocs.json index 5fbfcd72090a6..9d52361e05552 100644 --- a/api_docs/kbn_security_solution_features.devdocs.json +++ b/api_docs/kbn_security_solution_features.devdocs.json @@ -61,7 +61,7 @@ "AlertingKibanaPrivilege", " | undefined; cases?: readonly string[] | undefined; hidden?: boolean | undefined; description?: string | undefined; category: ", "AppCategory", - "; management?: { [sectionId: string]: readonly string[]; } | undefined; app: readonly string[]; readonly deprecated?: Readonly<{ notice: string; }> | undefined; privileges: { all: ", + "; management?: { [sectionId: string]: readonly string[]; } | undefined; app: readonly string[]; readonly deprecated?: Readonly<{ notice: string; replacedBy?: readonly string[] | undefined; }> | undefined; privileges: { all: ", { "pluginId": "features", "scope": "common", @@ -170,7 +170,7 @@ "AlertingKibanaPrivilege", " | undefined; cases?: readonly string[] | undefined; hidden?: boolean | undefined; description?: string | undefined; category: ", "AppCategory", - "; management?: { [sectionId: string]: readonly string[]; } | undefined; app: readonly string[]; readonly deprecated?: Readonly<{ notice: string; }> | undefined; privileges: { all: ", + "; management?: { [sectionId: string]: readonly string[]; } | undefined; app: readonly string[]; readonly deprecated?: Readonly<{ notice: string; replacedBy?: readonly string[] | undefined; }> | undefined; privileges: { all: ", { "pluginId": "features", "scope": "common", @@ -231,7 +231,11 @@ " | ", "ProductFeatureAssistantKey", " | ", - "ProductFeatureAttackDiscoveryKey" + "ProductFeatureAttackDiscoveryKey", + " | ", + "ProductFeatureTimelineFeatureKey", + " | ", + "ProductFeatureNotesFeatureKey" ], "path": "x-pack/solutions/security/packages/features/src/product_features_keys.ts", "deprecated": false, @@ -394,6 +398,31 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/security-solution-features", + "id": "def-common.ProductFeaturesNotesConfig", + "type": "Type", + "tags": [], + "label": "ProductFeaturesNotesConfig", + "description": [], + "signature": [ + "Map<", + "ProductFeatureNotesFeatureKey", + ", ", + { + "pluginId": "@kbn/security-solution-features", + "scope": "common", + "docId": "kibKbnSecuritySolutionFeaturesPluginApi", + "section": "def-common.ProductFeatureKibanaConfig", + "text": "ProductFeatureKibanaConfig" + }, + ">" + ], + "path": "x-pack/solutions/security/packages/features/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/security-solution-features", "id": "def-common.ProductFeaturesSecurityConfig", @@ -421,6 +450,31 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/security-solution-features", + "id": "def-common.ProductFeaturesTimelineConfig", + "type": "Type", + "tags": [], + "label": "ProductFeaturesTimelineConfig", + "description": [], + "signature": [ + "Map<", + "ProductFeatureTimelineFeatureKey", + ", ", + { + "pluginId": "@kbn/security-solution-features", + "scope": "common", + "docId": "kibKbnSecuritySolutionFeaturesPluginApi", + "section": "def-common.ProductFeatureKibanaConfig", + "text": "ProductFeatureKibanaConfig" + }, + ">" + ], + "path": "x-pack/solutions/security/packages/features/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/security-solution-features", "id": "def-common.SubFeaturesPrivileges", diff --git a/api_docs/kbn_security_solution_features.mdx b/api_docs/kbn_security_solution_features.mdx index 6c6ec20fad567..3408837890270 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-features'] --- import kbnSecuritySolutionFeaturesObj from './kbn_security_solution_features.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-threat-hunting-explore](https://github.com/orgs/elast | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 15 | 0 | 15 | 7 | +| 17 | 0 | 17 | 9 | ## Common diff --git a/api_docs/kbn_security_solution_navigation.mdx b/api_docs/kbn_security_solution_navigation.mdx index bf6665558049e..ae622fc7b5202 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: 2025-01-16 +date: 2025-01-21 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 bd8e88a01755d..1d882c8ce4134 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: 2025-01-16 +date: 2025-01-21 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 03ab5a93921bf..6a079a060c32f 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: 2025-01-16 +date: 2025-01-21 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_security_ui_components.mdx b/api_docs/kbn_security_ui_components.mdx index ae4975c5e2696..5c2f4db1dc656 100644 --- a/api_docs/kbn_security_ui_components.mdx +++ b/api_docs/kbn_security_ui_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-ui-components title: "@kbn/security-ui-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-ui-components plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-ui-components'] --- import kbnSecurityUiComponentsObj from './kbn_security_ui_components.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 924ba4ec64954..df932583051e9 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: 2025-01-16 +date: 2025-01-21 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 60df2516549f4..ad662fb91d5dc 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: 2025-01-16 +date: 2025-01-21 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.devdocs.json b/api_docs/kbn_securitysolution_ecs.devdocs.json index a03c6128f86c4..50add3f39ac5a 100644 --- a/api_docs/kbn_securitysolution_ecs.devdocs.json +++ b/api_docs/kbn_securitysolution_ecs.devdocs.json @@ -849,6 +849,27 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "@kbn/securitysolution-ecs", + "id": "def-common.EcsSecurityExtension.service", + "type": "Object", + "tags": [], + "label": "service", + "description": [], + "signature": [ + { + "pluginId": "@kbn/securitysolution-ecs", + "scope": "common", + "docId": "kibKbnSecuritysolutionEcsPluginApi", + "section": "def-common.ServiceEcs", + "text": "ServiceEcs" + }, + " | undefined" + ], + "path": "src/platform/packages/shared/kbn-securitysolution-ecs/src/index.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/securitysolution-ecs", "id": "def-common.EcsSecurityExtension._id", @@ -3469,6 +3490,160 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-ecs", + "id": "def-common.ServiceEcs", + "type": "Interface", + "tags": [], + "label": "ServiceEcs", + "description": [], + "path": "src/platform/packages/shared/kbn-securitysolution-ecs/src/service/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/securitysolution-ecs", + "id": "def-common.ServiceEcs.address", + "type": "Array", + "tags": [], + "label": "address", + "description": [], + "signature": [ + "string[] | undefined" + ], + "path": "src/platform/packages/shared/kbn-securitysolution-ecs/src/service/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/securitysolution-ecs", + "id": "def-common.ServiceEcs.environment", + "type": "Array", + "tags": [], + "label": "environment", + "description": [], + "signature": [ + "string[] | undefined" + ], + "path": "src/platform/packages/shared/kbn-securitysolution-ecs/src/service/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/securitysolution-ecs", + "id": "def-common.ServiceEcs.ephemeral_id", + "type": "Array", + "tags": [], + "label": "ephemeral_id", + "description": [], + "signature": [ + "string[] | undefined" + ], + "path": "src/platform/packages/shared/kbn-securitysolution-ecs/src/service/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/securitysolution-ecs", + "id": "def-common.ServiceEcs.id", + "type": "Array", + "tags": [], + "label": "id", + "description": [], + "signature": [ + "string[] | undefined" + ], + "path": "src/platform/packages/shared/kbn-securitysolution-ecs/src/service/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/securitysolution-ecs", + "id": "def-common.ServiceEcs.name", + "type": "Array", + "tags": [], + "label": "name", + "description": [], + "signature": [ + "string[] | undefined" + ], + "path": "src/platform/packages/shared/kbn-securitysolution-ecs/src/service/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/securitysolution-ecs", + "id": "def-common.ServiceEcs.node", + "type": "Object", + "tags": [], + "label": "node", + "description": [], + "signature": [ + "{ name: string[]; roles: string[]; role: string[]; } | undefined" + ], + "path": "src/platform/packages/shared/kbn-securitysolution-ecs/src/service/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/securitysolution-ecs", + "id": "def-common.ServiceEcs.roles", + "type": "Array", + "tags": [], + "label": "roles", + "description": [], + "signature": [ + "string[] | undefined" + ], + "path": "src/platform/packages/shared/kbn-securitysolution-ecs/src/service/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/securitysolution-ecs", + "id": "def-common.ServiceEcs.state", + "type": "Array", + "tags": [], + "label": "state", + "description": [], + "signature": [ + "string[] | undefined" + ], + "path": "src/platform/packages/shared/kbn-securitysolution-ecs/src/service/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/securitysolution-ecs", + "id": "def-common.ServiceEcs.type", + "type": "Array", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "string[] | undefined" + ], + "path": "src/platform/packages/shared/kbn-securitysolution-ecs/src/service/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/securitysolution-ecs", + "id": "def-common.ServiceEcs.version", + "type": "Array", + "tags": [], + "label": "version", + "description": [], + "signature": [ + "string[] | undefined" + ], + "path": "src/platform/packages/shared/kbn-securitysolution-ecs/src/service/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-ecs", "id": "def-common.SignalEcs", diff --git a/api_docs/kbn_securitysolution_ecs.mdx b/api_docs/kbn_securitysolution_ecs.mdx index 1799d84be9e05..48742e0d80252 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-ecs'] --- import kbnSecuritysolutionEcsObj from './kbn_securitysolution_ecs.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-threat-hunting-explore](https://github.com/orgs/elast | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 341 | 1 | 337 | 32 | +| 353 | 1 | 349 | 32 | ## Common diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 7a0724c9600e4..7d9973b4ed433 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: 2025-01-16 +date: 2025-01-21 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.devdocs.json b/api_docs/kbn_securitysolution_exception_list_components.devdocs.json index 85d199a001cc3..eec47a776e582 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.devdocs.json +++ b/api_docs/kbn_securitysolution_exception_list_components.devdocs.json @@ -868,7 +868,7 @@ "label": "formattedDateComponent", "description": [], "signature": [ - "\"symbol\" | \"object\" | \"source\" | \"meta\" | \"desc\" | \"filter\" | \"search\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"text\" | \"map\" | \"head\" | \"label\" | \"data\" | \"slot\" | \"style\" | \"title\" | \"form\" | \"path\" | \"code\" | \"pattern\" | \"set\" | \"summary\" | \"template\" | \"span\" | \"q\" | \"body\" | \"html\" | \"main\" | \"a\" | \"abbr\" | \"address\" | \"area\" | \"article\" | \"aside\" | \"audio\" | \"b\" | \"base\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"br\" | \"button\" | \"canvas\" | \"caption\" | \"center\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"img\" | \"input\" | \"ins\" | \"kbd\" | \"keygen\" | \"legend\" | \"li\" | \"mark\" | \"menu\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"output\" | \"p\" | \"param\" | \"picture\" | \"pre\" | \"progress\" | \"rp\" | \"rt\" | \"ruby\" | \"s\" | \"samp\" | \"script\" | \"section\" | \"select\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"textarea\" | \"tfoot\" | \"th\" | \"thead\" | \"time\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"var\" | \"video\" | \"wbr\" | \"webview\" | \"svg\" | \"animate\" | \"animateMotion\" | \"animateTransform\" | \"circle\" | \"clipPath\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"image\" | \"line\" | \"linearGradient\" | \"marker\" | \"mask\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"stop\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\" | \"view\" | React.ComponentType" + "\"symbol\" | \"object\" | \"source\" | \"meta\" | \"desc\" | \"filter\" | \"search\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"text\" | \"map\" | \"head\" | \"label\" | \"data\" | \"slot\" | \"style\" | \"title\" | \"form\" | \"summary\" | \"path\" | \"code\" | \"pattern\" | \"set\" | \"template\" | \"span\" | \"q\" | \"body\" | \"html\" | \"main\" | \"a\" | \"abbr\" | \"address\" | \"area\" | \"article\" | \"aside\" | \"audio\" | \"b\" | \"base\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"br\" | \"button\" | \"canvas\" | \"caption\" | \"center\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"img\" | \"input\" | \"ins\" | \"kbd\" | \"keygen\" | \"legend\" | \"li\" | \"mark\" | \"menu\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"output\" | \"p\" | \"param\" | \"picture\" | \"pre\" | \"progress\" | \"rp\" | \"rt\" | \"ruby\" | \"s\" | \"samp\" | \"script\" | \"section\" | \"select\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"textarea\" | \"tfoot\" | \"th\" | \"thead\" | \"time\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"var\" | \"video\" | \"wbr\" | \"webview\" | \"svg\" | \"animate\" | \"animateMotion\" | \"animateTransform\" | \"circle\" | \"clipPath\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"image\" | \"line\" | \"linearGradient\" | \"marker\" | \"mask\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"stop\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\" | \"view\" | React.ComponentType" ], "path": "x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/index.tsx", "deprecated": false, @@ -882,7 +882,7 @@ "label": "securityLinkAnchorComponent", "description": [], "signature": [ - "\"symbol\" | \"object\" | \"source\" | \"meta\" | \"desc\" | \"filter\" | \"search\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"text\" | \"map\" | \"head\" | \"label\" | \"data\" | \"slot\" | \"style\" | \"title\" | \"form\" | \"path\" | \"code\" | \"pattern\" | \"set\" | \"summary\" | \"template\" | \"span\" | \"q\" | \"body\" | \"html\" | \"main\" | \"a\" | \"abbr\" | \"address\" | \"area\" | \"article\" | \"aside\" | \"audio\" | \"b\" | \"base\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"br\" | \"button\" | \"canvas\" | \"caption\" | \"center\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"img\" | \"input\" | \"ins\" | \"kbd\" | \"keygen\" | \"legend\" | \"li\" | \"mark\" | \"menu\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"output\" | \"p\" | \"param\" | \"picture\" | \"pre\" | \"progress\" | \"rp\" | \"rt\" | \"ruby\" | \"s\" | \"samp\" | \"script\" | \"section\" | \"select\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"textarea\" | \"tfoot\" | \"th\" | \"thead\" | \"time\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"var\" | \"video\" | \"wbr\" | \"webview\" | \"svg\" | \"animate\" | \"animateMotion\" | \"animateTransform\" | \"circle\" | \"clipPath\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"image\" | \"line\" | \"linearGradient\" | \"marker\" | \"mask\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"stop\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\" | \"view\" | React.ComponentType" + "\"symbol\" | \"object\" | \"source\" | \"meta\" | \"desc\" | \"filter\" | \"search\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"text\" | \"map\" | \"head\" | \"label\" | \"data\" | \"slot\" | \"style\" | \"title\" | \"form\" | \"summary\" | \"path\" | \"code\" | \"pattern\" | \"set\" | \"template\" | \"span\" | \"q\" | \"body\" | \"html\" | \"main\" | \"a\" | \"abbr\" | \"address\" | \"area\" | \"article\" | \"aside\" | \"audio\" | \"b\" | \"base\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"br\" | \"button\" | \"canvas\" | \"caption\" | \"center\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"img\" | \"input\" | \"ins\" | \"kbd\" | \"keygen\" | \"legend\" | \"li\" | \"mark\" | \"menu\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"output\" | \"p\" | \"param\" | \"picture\" | \"pre\" | \"progress\" | \"rp\" | \"rt\" | \"ruby\" | \"s\" | \"samp\" | \"script\" | \"section\" | \"select\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"textarea\" | \"tfoot\" | \"th\" | \"thead\" | \"time\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"var\" | \"video\" | \"wbr\" | \"webview\" | \"svg\" | \"animate\" | \"animateMotion\" | \"animateTransform\" | \"circle\" | \"clipPath\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"image\" | \"line\" | \"linearGradient\" | \"marker\" | \"mask\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"stop\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\" | \"view\" | React.ComponentType" ], "path": "x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/index.tsx", "deprecated": false, @@ -1021,7 +1021,7 @@ "label": "securityLinkAnchorComponent", "description": [], "signature": [ - "\"symbol\" | \"object\" | \"source\" | \"meta\" | \"desc\" | \"filter\" | \"search\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"text\" | \"map\" | \"head\" | \"label\" | \"data\" | \"slot\" | \"style\" | \"title\" | \"form\" | \"path\" | \"code\" | \"pattern\" | \"set\" | \"summary\" | \"template\" | \"span\" | \"q\" | \"body\" | \"html\" | \"main\" | \"a\" | \"abbr\" | \"address\" | \"area\" | \"article\" | \"aside\" | \"audio\" | \"b\" | \"base\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"br\" | \"button\" | \"canvas\" | \"caption\" | \"center\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"img\" | \"input\" | \"ins\" | \"kbd\" | \"keygen\" | \"legend\" | \"li\" | \"mark\" | \"menu\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"output\" | \"p\" | \"param\" | \"picture\" | \"pre\" | \"progress\" | \"rp\" | \"rt\" | \"ruby\" | \"s\" | \"samp\" | \"script\" | \"section\" | \"select\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"textarea\" | \"tfoot\" | \"th\" | \"thead\" | \"time\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"var\" | \"video\" | \"wbr\" | \"webview\" | \"svg\" | \"animate\" | \"animateMotion\" | \"animateTransform\" | \"circle\" | \"clipPath\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"image\" | \"line\" | \"linearGradient\" | \"marker\" | \"mask\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"stop\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\" | \"view\" | React.ComponentType" + "\"symbol\" | \"object\" | \"source\" | \"meta\" | \"desc\" | \"filter\" | \"search\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"text\" | \"map\" | \"head\" | \"label\" | \"data\" | \"slot\" | \"style\" | \"title\" | \"form\" | \"summary\" | \"path\" | \"code\" | \"pattern\" | \"set\" | \"template\" | \"span\" | \"q\" | \"body\" | \"html\" | \"main\" | \"a\" | \"abbr\" | \"address\" | \"area\" | \"article\" | \"aside\" | \"audio\" | \"b\" | \"base\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"br\" | \"button\" | \"canvas\" | \"caption\" | \"center\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"img\" | \"input\" | \"ins\" | \"kbd\" | \"keygen\" | \"legend\" | \"li\" | \"mark\" | \"menu\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"output\" | \"p\" | \"param\" | \"picture\" | \"pre\" | \"progress\" | \"rp\" | \"rt\" | \"ruby\" | \"s\" | \"samp\" | \"script\" | \"section\" | \"select\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"textarea\" | \"tfoot\" | \"th\" | \"thead\" | \"time\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"var\" | \"video\" | \"wbr\" | \"webview\" | \"svg\" | \"animate\" | \"animateMotion\" | \"animateTransform\" | \"circle\" | \"clipPath\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"image\" | \"line\" | \"linearGradient\" | \"marker\" | \"mask\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"stop\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\" | \"view\" | React.ComponentType" ], "path": "x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/exception_item_card.tsx", "deprecated": false, @@ -1035,7 +1035,7 @@ "label": "formattedDateComponent", "description": [], "signature": [ - "\"symbol\" | \"object\" | \"source\" | \"meta\" | \"desc\" | \"filter\" | \"search\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"text\" | \"map\" | \"head\" | \"label\" | \"data\" | \"slot\" | \"style\" | \"title\" | \"form\" | \"path\" | \"code\" | \"pattern\" | \"set\" | \"summary\" | \"template\" | \"span\" | \"q\" | \"body\" | \"html\" | \"main\" | \"a\" | \"abbr\" | \"address\" | \"area\" | \"article\" | \"aside\" | \"audio\" | \"b\" | \"base\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"br\" | \"button\" | \"canvas\" | \"caption\" | \"center\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"img\" | \"input\" | \"ins\" | \"kbd\" | \"keygen\" | \"legend\" | \"li\" | \"mark\" | \"menu\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"output\" | \"p\" | \"param\" | \"picture\" | \"pre\" | \"progress\" | \"rp\" | \"rt\" | \"ruby\" | \"s\" | \"samp\" | \"script\" | \"section\" | \"select\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"textarea\" | \"tfoot\" | \"th\" | \"thead\" | \"time\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"var\" | \"video\" | \"wbr\" | \"webview\" | \"svg\" | \"animate\" | \"animateMotion\" | \"animateTransform\" | \"circle\" | \"clipPath\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"image\" | \"line\" | \"linearGradient\" | \"marker\" | \"mask\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"stop\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\" | \"view\" | React.ComponentType" + "\"symbol\" | \"object\" | \"source\" | \"meta\" | \"desc\" | \"filter\" | \"search\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"text\" | \"map\" | \"head\" | \"label\" | \"data\" | \"slot\" | \"style\" | \"title\" | \"form\" | \"summary\" | \"path\" | \"code\" | \"pattern\" | \"set\" | \"template\" | \"span\" | \"q\" | \"body\" | \"html\" | \"main\" | \"a\" | \"abbr\" | \"address\" | \"area\" | \"article\" | \"aside\" | \"audio\" | \"b\" | \"base\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"br\" | \"button\" | \"canvas\" | \"caption\" | \"center\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"img\" | \"input\" | \"ins\" | \"kbd\" | \"keygen\" | \"legend\" | \"li\" | \"mark\" | \"menu\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"output\" | \"p\" | \"param\" | \"picture\" | \"pre\" | \"progress\" | \"rp\" | \"rt\" | \"ruby\" | \"s\" | \"samp\" | \"script\" | \"section\" | \"select\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"textarea\" | \"tfoot\" | \"th\" | \"thead\" | \"time\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"var\" | \"video\" | \"wbr\" | \"webview\" | \"svg\" | \"animate\" | \"animateMotion\" | \"animateTransform\" | \"circle\" | \"clipPath\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"image\" | \"line\" | \"linearGradient\" | \"marker\" | \"mask\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"stop\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\" | \"view\" | React.ComponentType" ], "path": "x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/exception_item_card.tsx", "deprecated": false, @@ -1161,7 +1161,7 @@ "label": "showValueListModal", "description": [], "signature": [ - "\"symbol\" | \"object\" | \"source\" | \"meta\" | \"desc\" | \"filter\" | \"search\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"text\" | \"map\" | \"head\" | \"label\" | \"data\" | \"slot\" | \"style\" | \"title\" | \"form\" | \"path\" | \"code\" | \"pattern\" | \"set\" | \"summary\" | \"template\" | \"span\" | \"q\" | \"body\" | \"html\" | \"main\" | \"a\" | \"abbr\" | \"address\" | \"area\" | \"article\" | \"aside\" | \"audio\" | \"b\" | \"base\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"br\" | \"button\" | \"canvas\" | \"caption\" | \"center\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"img\" | \"input\" | \"ins\" | \"kbd\" | \"keygen\" | \"legend\" | \"li\" | \"mark\" | \"menu\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"output\" | \"p\" | \"param\" | \"picture\" | \"pre\" | \"progress\" | \"rp\" | \"rt\" | \"ruby\" | \"s\" | \"samp\" | \"script\" | \"section\" | \"select\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"textarea\" | \"tfoot\" | \"th\" | \"thead\" | \"time\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"var\" | \"video\" | \"wbr\" | \"webview\" | \"svg\" | \"animate\" | \"animateMotion\" | \"animateTransform\" | \"circle\" | \"clipPath\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"image\" | \"line\" | \"linearGradient\" | \"marker\" | \"mask\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"stop\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\" | \"view\" | React.ComponentType" + "\"symbol\" | \"object\" | \"source\" | \"meta\" | \"desc\" | \"filter\" | \"search\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"text\" | \"map\" | \"head\" | \"label\" | \"data\" | \"slot\" | \"style\" | \"title\" | \"form\" | \"summary\" | \"path\" | \"code\" | \"pattern\" | \"set\" | \"template\" | \"span\" | \"q\" | \"body\" | \"html\" | \"main\" | \"a\" | \"abbr\" | \"address\" | \"area\" | \"article\" | \"aside\" | \"audio\" | \"b\" | \"base\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"br\" | \"button\" | \"canvas\" | \"caption\" | \"center\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"img\" | \"input\" | \"ins\" | \"kbd\" | \"keygen\" | \"legend\" | \"li\" | \"mark\" | \"menu\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"output\" | \"p\" | \"param\" | \"picture\" | \"pre\" | \"progress\" | \"rp\" | \"rt\" | \"ruby\" | \"s\" | \"samp\" | \"script\" | \"section\" | \"select\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"textarea\" | \"tfoot\" | \"th\" | \"thead\" | \"time\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"var\" | \"video\" | \"wbr\" | \"webview\" | \"svg\" | \"animate\" | \"animateMotion\" | \"animateTransform\" | \"circle\" | \"clipPath\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"image\" | \"line\" | \"linearGradient\" | \"marker\" | \"mask\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"stop\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\" | \"view\" | React.ComponentType" ], "path": "x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/exception_item_card.tsx", "deprecated": false, diff --git a/api_docs/kbn_securitysolution_exception_list_components.mdx b/api_docs/kbn_securitysolution_exception_list_components.mdx index b9d01df8e4078..fc3c9707cfbb2 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: 2025-01-16 +date: 2025-01-21 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 adebbdd6b3928..0c69b52f45d01 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: 2025-01-16 +date: 2025-01-21 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 36ca3802f6565..dfe68b613e0d6 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: 2025-01-16 +date: 2025-01-21 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 e373811721132..2dbe446f3d9cd 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: 2025-01-16 +date: 2025-01-21 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 4e09dd94ddb06..6aa0d41df1ac8 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: 2025-01-16 +date: 2025-01-21 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 6bae2a08b0426..16264833db6a8 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: 2025-01-16 +date: 2025-01-21 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 26625cee66243..2fdb546f97e53 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: 2025-01-16 +date: 2025-01-21 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 9f81ff6b5037d..7d87e5b0eaefb 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: 2025-01-16 +date: 2025-01-21 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 19ac023d812e6..b6d700daaaa25 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: 2025-01-16 +date: 2025-01-21 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 f4558d6d3919e..24c24dab970c8 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: 2025-01-16 +date: 2025-01-21 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 03a10018969c0..b570a941eb893 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: 2025-01-16 +date: 2025-01-21 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 a66c9141d455c..6cbd28a598f94 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: 2025-01-16 +date: 2025-01-21 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 277cca7b5ecaf..b8dbaf64254d5 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: 2025-01-16 +date: 2025-01-21 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 27e19592e1362..dd16f5252dfa3 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: 2025-01-16 +date: 2025-01-21 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 463662e83240f..bfac5acb0700c 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository_client.mdx b/api_docs/kbn_server_route_repository_client.mdx index cadae476eb76c..4876acd1871f3 100644 --- a/api_docs/kbn_server_route_repository_client.mdx +++ b/api_docs/kbn_server_route_repository_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository-client title: "@kbn/server-route-repository-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository-client plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository-client'] --- import kbnServerRouteRepositoryClientObj from './kbn_server_route_repository_client.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository_utils.mdx b/api_docs/kbn_server_route_repository_utils.mdx index 372ffa7f3651a..515aecf73e78a 100644 --- a/api_docs/kbn_server_route_repository_utils.mdx +++ b/api_docs/kbn_server_route_repository_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository-utils title: "@kbn/server-route-repository-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository-utils plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository-utils'] --- import kbnServerRouteRepositoryUtilsObj from './kbn_server_route_repository_utils.devdocs.json'; diff --git a/api_docs/kbn_serverless_common_settings.mdx b/api_docs/kbn_serverless_common_settings.mdx index fb7953a4ffc76..53035a877c98e 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: 2025-01-16 +date: 2025-01-21 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 ad91194a634f0..caef62f8506ab 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: 2025-01-16 +date: 2025-01-21 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 9dc4954314c42..0b0dcc38618c2 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: 2025-01-16 +date: 2025-01-21 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 ced3d7b9b9a40..11c3fa3354417 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: 2025-01-16 +date: 2025-01-21 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 0af2d7fb78ae3..3c8dd29814e48 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: 2025-01-16 +date: 2025-01-21 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 fcc9bd31bb2af..6f88b396eea27 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: 2025-01-16 +date: 2025-01-21 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 743df4054b1ce..a90d81d9b1378 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: 2025-01-16 +date: 2025-01-21 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 999bfa1f510f9..76d81e713a574 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: 2025-01-16 +date: 2025-01-21 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 5df0577c343f2..c4a98f7767455 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: 2025-01-16 +date: 2025-01-21 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 3d5eb0dedfc02..b047a50727f64 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: 2025-01-16 +date: 2025-01-21 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 6c72c5444bdec..24c621bfed303 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: 2025-01-16 +date: 2025-01-21 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 950c70f26c154..3b42b515b27dd 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: 2025-01-16 +date: 2025-01-21 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 d8b9c71bc691d..961f95d41361c 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: 2025-01-16 +date: 2025-01-21 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 e1ea6a7feb98e..003c731ed3a80 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: 2025-01-16 +date: 2025-01-21 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 57d282538e16b..3c6a814819705 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: 2025-01-16 +date: 2025-01-21 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 36c8bb0ba3593..b6ff0d246521c 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: 2025-01-16 +date: 2025-01-21 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 35e210e81f978..0a74a31dccd2c 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: 2025-01-16 +date: 2025-01-21 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 608dec091ee7a..4bcd8c85c891a 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: 2025-01-16 +date: 2025-01-21 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 5f68c92690663..f42ec1d9131a3 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: 2025-01-16 +date: 2025-01-21 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 dfff0962e3e2d..cde16c87d9d19 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: 2025-01-16 +date: 2025-01-21 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 d4ce8758ecbea..8cf8c064e1cc3 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: 2025-01-16 +date: 2025-01-21 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 74989beae568e..b5d893028d97c 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: 2025-01-16 +date: 2025-01-21 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 9fde8006bd997..4354477b175b7 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: 2025-01-16 +date: 2025-01-21 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 cd985aee3b1c2..37eafdfa829e2 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: 2025-01-16 +date: 2025-01-21 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 894a20e8228d3..aeaaffb8fde49 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: 2025-01-16 +date: 2025-01-21 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 f9faf808adb71..2d283f20f545a 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: 2025-01-16 +date: 2025-01-21 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 08c24189e34e5..7a79a2c446dd1 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: 2025-01-16 +date: 2025-01-21 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 ad5a002e46fee..a9b42a71e679f 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: 2025-01-16 +date: 2025-01-21 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 e2b3d5f5bc7cb..2856de2e2ed46 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: 2025-01-16 +date: 2025-01-21 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 0de39bb19c3ab..bf102d7a3016a 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: 2025-01-16 +date: 2025-01-21 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 52ac624280d7e..9e4f2649c2b63 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: 2025-01-16 +date: 2025-01-21 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 3be511835de37..bca8bb5e79482 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: 2025-01-16 +date: 2025-01-21 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 5b10c804d5969..0d5133b06aac9 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: 2025-01-16 +date: 2025-01-21 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 4fd5ad98ab03f..cbb5387e53de6 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: 2025-01-16 +date: 2025-01-21 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 670cb9223fab9..4b99ee27e9179 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: 2025-01-16 +date: 2025-01-21 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 c6812be006c5d..295996abf2eba 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: 2025-01-16 +date: 2025-01-21 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 16591b984954a..887aa04e5f486 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: 2025-01-16 +date: 2025-01-21 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 eed48b5272cd9..0f0e3625a280a 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: 2025-01-16 +date: 2025-01-21 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 c8362e2841d76..31513c1f551a8 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: 2025-01-16 +date: 2025-01-21 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 ef685126a8184..b8f37487fd8eb 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: 2025-01-16 +date: 2025-01-21 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 5ad40a048951e..61e94cbb23e2f 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: 2025-01-16 +date: 2025-01-21 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 6d4d341a126a2..784ab03b46f38 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: 2025-01-16 +date: 2025-01-21 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 63cc7720d7c25..83ae064a36508 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: 2025-01-16 +date: 2025-01-21 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 e76dafbcccc6c..4082c8ae53e8d 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: 2025-01-16 +date: 2025-01-21 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 8df549a00e2a4..567c0e8daa3c6 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: 2025-01-16 +date: 2025-01-21 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_table_persist.mdx b/api_docs/kbn_shared_ux_table_persist.mdx index 5917dfcdfec7f..a5737fc125689 100644 --- a/api_docs/kbn_shared_ux_table_persist.mdx +++ b/api_docs/kbn_shared_ux_table_persist.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-table-persist title: "@kbn/shared-ux-table-persist" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-table-persist plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-table-persist'] --- import kbnSharedUxTablePersistObj from './kbn_shared_ux_table_persist.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index 7ac9fce3b3b79..fff51caff3d0a 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: 2025-01-16 +date: 2025-01-21 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.devdocs.json b/api_docs/kbn_slo_schema.devdocs.json index a12d24ea6ee25..da95b6af32208 100644 --- a/api_docs/kbn_slo_schema.devdocs.json +++ b/api_docs/kbn_slo_schema.devdocs.json @@ -835,7 +835,7 @@ "label": "FindSLODefinitionsResponse", "description": [], "signature": [ - "{ page: number; perPage: number; total: number; results: { id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; }[]; }" + "{ page: number; perPage: number; total: number; results: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { createdBy?: string | undefined; updatedBy?: string | undefined; })[]; }" ], "path": "x-pack/platform/packages/shared/kbn-slo-schema/src/rest_specs/routes/find_definition.ts", "deprecated": false, @@ -895,7 +895,7 @@ "label": "FindSLOResponse", "description": [], "signature": [ - "{ page: number; perPage: number; total: number; results: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; fiveMinuteBurnRate: number; oneHourBurnRate: number; oneDayBurnRate: number; } & { summaryUpdatedAt?: string | null | undefined; }; groupings: { [x: string]: string | number; }; } & { instanceId?: string | undefined; meta?: { synthetics?: { monitorId: string; locationId: string; configId: string; } | undefined; } | undefined; remote?: { remoteName: string; kibanaUrl: string; } | undefined; })[]; } & { searchAfter?: (string | number)[] | undefined; size?: number | undefined; }" + "{ page: number; perPage: number; total: number; results: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { createdBy?: string | undefined; updatedBy?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; fiveMinuteBurnRate: number; oneHourBurnRate: number; oneDayBurnRate: number; } & { summaryUpdatedAt?: string | null | undefined; }; groupings: { [x: string]: string | number; }; } & { instanceId?: string | undefined; meta?: { synthetics?: { monitorId: string; locationId: string; configId: string; } | undefined; } | undefined; remote?: { remoteName: string; kibanaUrl: string; } | undefined; })[]; } & { searchAfter?: (string | number)[] | undefined; size?: number | undefined; }" ], "path": "x-pack/platform/packages/shared/kbn-slo-schema/src/rest_specs/routes/find.ts", "deprecated": false, @@ -1008,7 +1008,7 @@ "label": "GetSLOResponse", "description": [], "signature": [ - "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; fiveMinuteBurnRate: number; oneHourBurnRate: number; oneDayBurnRate: number; } & { summaryUpdatedAt?: string | null | undefined; }; groupings: { [x: string]: string | number; }; } & { instanceId?: string | undefined; meta?: { synthetics?: { monitorId: string; locationId: string; configId: string; } | undefined; } | undefined; remote?: { remoteName: string; kibanaUrl: string; } | undefined; }" + "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { createdBy?: string | undefined; updatedBy?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; fiveMinuteBurnRate: number; oneHourBurnRate: number; oneDayBurnRate: number; } & { summaryUpdatedAt?: string | null | undefined; }; groupings: { [x: string]: string | number; }; } & { instanceId?: string | undefined; meta?: { synthetics?: { monitorId: string; locationId: string; configId: string; } | undefined; } | undefined; remote?: { remoteName: string; kibanaUrl: string; } | undefined; }" ], "path": "x-pack/platform/packages/shared/kbn-slo-schema/src/rest_specs/routes/get.ts", "deprecated": false, @@ -1278,7 +1278,7 @@ "label": "ResetSLOResponse", "description": [], "signature": [ - "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; }" + "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { createdBy?: string | undefined; updatedBy?: string | undefined; }" ], "path": "x-pack/platform/packages/shared/kbn-slo-schema/src/rest_specs/routes/reset.ts", "deprecated": false, @@ -1293,7 +1293,7 @@ "label": "SLODefinitionResponse", "description": [], "signature": [ - "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; }" + "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { createdBy?: string | undefined; updatedBy?: string | undefined; }" ], "path": "x-pack/platform/packages/shared/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -1308,7 +1308,7 @@ "label": "SLOWithSummaryResponse", "description": [], "signature": [ - "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; fiveMinuteBurnRate: number; oneHourBurnRate: number; oneDayBurnRate: number; } & { summaryUpdatedAt?: string | null | undefined; }; groupings: { [x: string]: string | number; }; } & { instanceId?: string | undefined; meta?: { synthetics?: { monitorId: string; locationId: string; configId: string; } | undefined; } | undefined; remote?: { remoteName: string; kibanaUrl: string; } | undefined; }" + "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { createdBy?: string | undefined; updatedBy?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; fiveMinuteBurnRate: number; oneHourBurnRate: number; oneDayBurnRate: number; } & { summaryUpdatedAt?: string | null | undefined; }; groupings: { [x: string]: string | number; }; } & { instanceId?: string | undefined; meta?: { synthetics?: { monitorId: string; locationId: string; configId: string; } | undefined; } | undefined; remote?: { remoteName: string; kibanaUrl: string; } | undefined; }" ], "path": "x-pack/platform/packages/shared/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -1483,7 +1483,7 @@ "label": "UpdateSLOResponse", "description": [], "signature": [ - "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; }" + "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { createdBy?: string | undefined; updatedBy?: string | undefined; }" ], "path": "x-pack/platform/packages/shared/kbn-slo-schema/src/rest_specs/routes/update.ts", "deprecated": false, @@ -3940,6 +3940,8 @@ "; results: ", "ArrayC", "<", + "IntersectionC", + "<[", "TypeC", "<{ id: ", "Type", @@ -5511,7 +5513,13 @@ "StringC", "]>>]>; version: ", "NumberC", - "; }>>; }>" + "; }>, ", + "PartialC", + "<{ createdBy: ", + "StringC", + "; updatedBy: ", + "StringC", + "; }>]>>; }>" ], "path": "x-pack/platform/packages/shared/kbn-slo-schema/src/rest_specs/routes/find_definition.ts", "deprecated": false, @@ -5716,6 +5724,8 @@ "<", "IntersectionC", "<[", + "IntersectionC", + "<[", "TypeC", "<{ id: ", "Type", @@ -7288,6 +7298,12 @@ "]>>]>; version: ", "NumberC", "; }>, ", + "PartialC", + "<{ createdBy: ", + "StringC", + "; updatedBy: ", + "StringC", + "; }>]>, ", "TypeC", "<{ summary: ", "IntersectionC", @@ -9124,6 +9140,8 @@ "label": "getSLOResponseSchema", "description": [], "signature": [ + "IntersectionC", + "<[", "IntersectionC", "<[", "TypeC", @@ -10698,6 +10716,12 @@ "]>>]>; version: ", "NumberC", "; }>, ", + "PartialC", + "<{ createdBy: ", + "StringC", + "; updatedBy: ", + "StringC", + "; }>]>, ", "TypeC", "<{ summary: ", "IntersectionC", @@ -13983,6 +14007,8 @@ "label": "resetSLOResponseSchema", "description": [], "signature": [ + "IntersectionC", + "<[", "TypeC", "<{ id: ", "Type", @@ -15554,7 +15580,13 @@ "StringC", "]>>]>; version: ", "NumberC", - "; }>" + "; }>, ", + "PartialC", + "<{ createdBy: ", + "StringC", + "; updatedBy: ", + "StringC", + "; }>]>" ], "path": "x-pack/platform/packages/shared/kbn-slo-schema/src/rest_specs/routes/reset.ts", "deprecated": false, @@ -15661,6 +15693,8 @@ "label": "sloDefinitionSchema", "description": [], "signature": [ + "IntersectionC", + "<[", "TypeC", "<{ id: ", "Type", @@ -17232,7 +17266,13 @@ "StringC", "]>>]>; version: ", "NumberC", - "; }>" + "; }>, ", + "PartialC", + "<{ createdBy: ", + "StringC", + "; updatedBy: ", + "StringC", + "; }>]>" ], "path": "x-pack/platform/packages/shared/kbn-slo-schema/src/schema/slo.ts", "deprecated": false, @@ -17369,6 +17409,8 @@ "label": "sloWithDataResponseSchema", "description": [], "signature": [ + "IntersectionC", + "<[", "IntersectionC", "<[", "TypeC", @@ -18943,6 +18985,12 @@ "]>>]>; version: ", "NumberC", "; }>, ", + "PartialC", + "<{ createdBy: ", + "StringC", + "; updatedBy: ", + "StringC", + "; }>]>, ", "TypeC", "<{ summary: ", "IntersectionC", @@ -21795,6 +21843,8 @@ "label": "updateSLOResponseSchema", "description": [], "signature": [ + "IntersectionC", + "<[", "TypeC", "<{ id: ", "Type", @@ -23366,7 +23416,13 @@ "StringC", "]>>]>; version: ", "NumberC", - "; }>" + "; }>, ", + "PartialC", + "<{ createdBy: ", + "StringC", + "; updatedBy: ", + "StringC", + "; }>]>" ], "path": "x-pack/platform/packages/shared/kbn-slo-schema/src/rest_specs/routes/update.ts", "deprecated": false, diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index b4fbca722305f..66437148337e6 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: 2025-01-16 +date: 2025-01-21 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 33e2c8ba3952f..fce8093aa312b 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: 2025-01-16 +date: 2025-01-21 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 f8cbe05b75611..0974f952e5cd8 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-predicates'] --- import kbnSortPredicatesObj from './kbn_sort_predicates.devdocs.json'; diff --git a/api_docs/kbn_sse_utils.mdx b/api_docs/kbn_sse_utils.mdx index 6fc44905f4c96..367f95c70c8fc 100644 --- a/api_docs/kbn_sse_utils.mdx +++ b/api_docs/kbn_sse_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sse-utils title: "@kbn/sse-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sse-utils plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sse-utils'] --- import kbnSseUtilsObj from './kbn_sse_utils.devdocs.json'; diff --git a/api_docs/kbn_sse_utils_client.mdx b/api_docs/kbn_sse_utils_client.mdx index 44b2a72f96bab..2b5dc63390254 100644 --- a/api_docs/kbn_sse_utils_client.mdx +++ b/api_docs/kbn_sse_utils_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sse-utils-client title: "@kbn/sse-utils-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sse-utils-client plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sse-utils-client'] --- import kbnSseUtilsClientObj from './kbn_sse_utils_client.devdocs.json'; diff --git a/api_docs/kbn_sse_utils_server.mdx b/api_docs/kbn_sse_utils_server.mdx index 692d295712ed4..6a67f30fcb63d 100644 --- a/api_docs/kbn_sse_utils_server.mdx +++ b/api_docs/kbn_sse_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sse-utils-server title: "@kbn/sse-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sse-utils-server plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sse-utils-server'] --- import kbnSseUtilsServerObj from './kbn_sse_utils_server.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index e8009f97a53d0..666b056f6ccfe 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: 2025-01-16 +date: 2025-01-21 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 9b286ca56e56d..ddc8053256065 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: 2025-01-16 +date: 2025-01-21 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 734b39e365e13..29588d716ec1f 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_streams_schema.mdx b/api_docs/kbn_streams_schema.mdx index d947177b38755..3f6efe0b668a5 100644 --- a/api_docs/kbn_streams_schema.mdx +++ b/api_docs/kbn_streams_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-streams-schema title: "@kbn/streams-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/streams-schema plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/streams-schema'] --- import kbnStreamsSchemaObj from './kbn_streams_schema.devdocs.json'; diff --git a/api_docs/kbn_synthetics_e2e.mdx b/api_docs/kbn_synthetics_e2e.mdx index 9b86150aced09..f311b314db1b3 100644 --- a/api_docs/kbn_synthetics_e2e.mdx +++ b/api_docs/kbn_synthetics_e2e.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-synthetics-e2e title: "@kbn/synthetics-e2e" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/synthetics-e2e plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/synthetics-e2e'] --- import kbnSyntheticsE2eObj from './kbn_synthetics_e2e.devdocs.json'; diff --git a/api_docs/kbn_synthetics_private_location.mdx b/api_docs/kbn_synthetics_private_location.mdx index 6786c3d7f7358..2f7d8ce7ac043 100644 --- a/api_docs/kbn_synthetics_private_location.mdx +++ b/api_docs/kbn_synthetics_private_location.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-synthetics-private-location title: "@kbn/synthetics-private-location" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/synthetics-private-location plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/synthetics-private-location'] --- import kbnSyntheticsPrivateLocationObj from './kbn_synthetics_private_location.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 35efbcacec916..2821766f74193 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: 2025-01-16 +date: 2025-01-21 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 e20fe86355abb..05539d0c53c0e 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: 2025-01-16 +date: 2025-01-21 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 dbe571a7ece61..1d97eb3b749cb 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: 2025-01-16 +date: 2025-01-21 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 251d1fbc2c314..576ce63e724dd 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: 2025-01-16 +date: 2025-01-21 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 3071cb860e783..31bf53eb8579d 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_timerange.mdx b/api_docs/kbn_timerange.mdx index 9206cdfacd6f6..f1a2748215baa 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: 2025-01-16 +date: 2025-01-21 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 aaefdb2f16e8a..774f1a7a3623a 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_transpose_utils.mdx b/api_docs/kbn_transpose_utils.mdx index 0d92961e96aeb..35f53e92c5f60 100644 --- a/api_docs/kbn_transpose_utils.mdx +++ b/api_docs/kbn_transpose_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-transpose-utils title: "@kbn/transpose-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/transpose-utils plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/transpose-utils'] --- import kbnTransposeUtilsObj from './kbn_transpose_utils.devdocs.json'; diff --git a/api_docs/kbn_triggers_actions_ui_types.mdx b/api_docs/kbn_triggers_actions_ui_types.mdx index 14051b3e0a361..f57723bb036f5 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: 2025-01-16 +date: 2025-01-21 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 89dc17d58d64d..f5be09d7a9f1d 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: 2025-01-16 +date: 2025-01-21 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 8f0b1585ab067..33015c03bdb95 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: 2025-01-16 +date: 2025-01-21 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 408b91cb9b7b0..3aa8d7077d854 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: 2025-01-16 +date: 2025-01-21 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 0c35fce8779b2..e5ccf77e883e8 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: 2025-01-16 +date: 2025-01-21 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 cb1ec236eb687..e05f49d79e212 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: 2025-01-16 +date: 2025-01-21 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 9d860af1807f0..3bbf317eabdd6 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: 2025-01-16 +date: 2025-01-21 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.devdocs.json b/api_docs/kbn_unified_data_table.devdocs.json index ec9a3ec77fc8e..56298d9f1de92 100644 --- a/api_docs/kbn_unified_data_table.devdocs.json +++ b/api_docs/kbn_unified_data_table.devdocs.json @@ -2307,6 +2307,10 @@ { "plugin": "securitySolution", "path": "x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/solutions/security/plugins/security_solution/public/asset_inventory/pages/all_assets.tsx" } ] }, diff --git a/api_docs/kbn_unified_data_table.mdx b/api_docs/kbn_unified_data_table.mdx index d123738e04dee..e3f6f3e765869 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: 2025-01-16 +date: 2025-01-21 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 6d706fe0e23a1..a9b67fb6b3995 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: 2025-01-16 +date: 2025-01-21 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 6577297f86056..6e5314e5a9b3d 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: 2025-01-16 +date: 2025-01-21 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 46abca29fec04..829570b28eb25 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: 2025-01-16 +date: 2025-01-21 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 4c15224ca81f2..f970c59275a2e 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: 2025-01-16 +date: 2025-01-21 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 401982ed63db5..831887bcc46fa 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: 2025-01-16 +date: 2025-01-21 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 aa3b888b622d7..2d48f0e759d30 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: 2025-01-16 +date: 2025-01-21 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 231980c05f6c2..520c4b70d99e7 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: 2025-01-16 +date: 2025-01-21 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 ba187e5bfc2e6..43a9ecc32a9cf 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: 2025-01-16 +date: 2025-01-21 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 a911d80b16353..24727c3b5631b 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: 2025-01-16 +date: 2025-01-21 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 1c4b4a127d710..ce6bdf8e545f7 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: 2025-01-16 +date: 2025-01-21 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 9b0ed4c664db5..77a5315fc815f 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: 2025-01-16 +date: 2025-01-21 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 45afef9b15762..28bf3e1df4c2e 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: 2025-01-16 +date: 2025-01-21 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 b98da82d6ef0b..3f1c11598ce5d 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: 2025-01-16 +date: 2025-01-21 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.mdx b/api_docs/kbn_zod.mdx index 89d5ff0c63512..5206b009b5c18 100644 --- a/api_docs/kbn_zod.mdx +++ b/api_docs/kbn_zod.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-zod title: "@kbn/zod" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/zod plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/zod'] --- import kbnZodObj from './kbn_zod.devdocs.json'; diff --git a/api_docs/kbn_zod_helpers.mdx b/api_docs/kbn_zod_helpers.mdx index 2737be04f1b0a..84e5bd18c1193 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: 2025-01-16 +date: 2025-01-21 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 c496a9b10f824..aa24a898c64d4 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: 2025-01-16 +date: 2025-01-21 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 bc314b9a90fba..6ab6ba8125d5c 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: 2025-01-16 +date: 2025-01-21 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 73d11240f5b6c..3d3998bbbc34b 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: 2025-01-16 +date: 2025-01-21 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 34ade721f7e6c..b986ac36e2bab 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: 2025-01-16 +date: 2025-01-21 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 46a36cb54db08..8c7d1ad8de860 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: 2025-01-16 +date: 2025-01-21 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 f789a77e4ebc1..a679975dc7f63 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: 2025-01-16 +date: 2025-01-21 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 ab2eba683948a..8e93734feb77b 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: 2025-01-16 +date: 2025-01-21 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 5f3383c33cf11..3e651eb5be26f 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: 2025-01-16 +date: 2025-01-21 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 8277eeba6cd34..a9da51e9674de 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: 2025-01-16 +date: 2025-01-21 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 93a197366eb7d..22ca3cfb82ce2 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/llm_tasks.devdocs.json b/api_docs/llm_tasks.devdocs.json index 39638b49a1e87..eedd2bc9614d7 100644 --- a/api_docs/llm_tasks.devdocs.json +++ b/api_docs/llm_tasks.devdocs.json @@ -11,9 +11,333 @@ "server": { "classes": [], "functions": [], - "interfaces": [], + "interfaces": [ + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationParams", + "type": "Interface", + "tags": [], + "label": "RetrieveDocumentationParams", + "description": [ + "\nParameters for {@link RetrieveDocumentationAPI}" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationParams.searchTerm", + "type": "string", + "tags": [], + "label": "searchTerm", + "description": [ + "\nThe search term to perform semantic text with.\nE.g. \"What is Kibana Lens?\"" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationParams.max", + "type": "number", + "tags": [], + "label": "max", + "description": [ + "\nMaximum number of documents to return.\nDefaults to 3." + ], + "signature": [ + "number | undefined" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationParams.products", + "type": "Array", + "tags": [], + "label": "products", + "description": [ + "\nOptional list of products to restrict the search to." + ], + "signature": [ + "(\"security\" | \"kibana\" | \"observability\" | \"elasticsearch\")[] | undefined" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationParams.maxDocumentTokens", + "type": "number", + "tags": [], + "label": "maxDocumentTokens", + "description": [ + "\nThe maximum number of tokens to return *per document*.\nDocuments exceeding this limit will go through token reduction.\n\nDefaults to `1000`." + ], + "signature": [ + "number | undefined" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationParams.tokenReductionStrategy", + "type": "CompoundType", + "tags": [], + "label": "tokenReductionStrategy", + "description": [ + "\nThe token reduction strategy to apply for documents exceeding max token count.\n- \"highlight\": Use Elasticsearch semantic highlighter to build a summary (concatenating highlights)\n- \"truncate\": Will keep the N first tokens\n- \"summarize\": Will call the LLM asking to generate a contextualized summary of the document\n\nOverall, `summarize` is more efficient, but significantly slower, given that an additional\nLLM call will be performed.\n\nDefaults to `highlight`" + ], + "signature": [ + "\"highlight\" | \"truncate\" | \"summarize\" | undefined" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationParams.request", + "type": "Object", + "tags": [], + "label": "request", + "description": [ + "\nThe request that initiated the task." + ], + "signature": [ + "KibanaRequest", + "" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationParams.connectorId", + "type": "string", + "tags": [], + "label": "connectorId", + "description": [ + "\nId of the LLM connector to use for the task." + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationParams.functionCalling", + "type": "CompoundType", + "tags": [], + "label": "functionCalling", + "description": [ + "\nOptional functionCalling parameter to pass down to the inference APIs." + ], + "signature": [ + { + "pluginId": "@kbn/inference-common", + "scope": "common", + "docId": "kibKbnInferenceCommonPluginApi", + "section": "def-common.FunctionCallingMode", + "text": "FunctionCallingMode" + }, + " | undefined" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationResult", + "type": "Interface", + "tags": [], + "label": "RetrieveDocumentationResult", + "description": [ + "\nResponse type for {@link RetrieveDocumentationAPI}" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationResult.success", + "type": "boolean", + "tags": [], + "label": "success", + "description": [ + "whether the call was successful or not" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationResult.documents", + "type": "Array", + "tags": [], + "label": "documents", + "description": [ + "List of results for this search" + ], + "signature": [ + { + "pluginId": "llmTasks", + "scope": "server", + "docId": "kibLlmTasksPluginApi", + "section": "def-server.RetrieveDocumentationResultDoc", + "text": "RetrieveDocumentationResultDoc" + }, + "[]" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationResultDoc", + "type": "Interface", + "tags": [], + "label": "RetrieveDocumentationResultDoc", + "description": [ + "\nIndividual result item in a {@link RetrieveDocumentationResult}" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationResultDoc.title", + "type": "string", + "tags": [], + "label": "title", + "description": [ + "title of the document" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationResultDoc.url", + "type": "string", + "tags": [], + "label": "url", + "description": [ + "full url to the online documentation" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationResultDoc.content", + "type": "string", + "tags": [], + "label": "content", + "description": [ + "full content of the doc article" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationResultDoc.summarized", + "type": "boolean", + "tags": [], + "label": "summarized", + "description": [ + "true if content exceeded max token length and had to go through token reduction" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], "enums": [], - "misc": [], + "misc": [ + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationAPI", + "type": "Type", + "tags": [], + "label": "RetrieveDocumentationAPI", + "description": [ + "\nRetrieve documentation API" + ], + "signature": [ + "(options: ", + { + "pluginId": "llmTasks", + "scope": "server", + "docId": "kibLlmTasksPluginApi", + "section": "def-server.RetrieveDocumentationParams", + "text": "RetrieveDocumentationParams" + }, + ") => Promise<", + { + "pluginId": "llmTasks", + "scope": "server", + "docId": "kibLlmTasksPluginApi", + "section": "def-server.RetrieveDocumentationResult", + "text": "RetrieveDocumentationResult" + }, + ">" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "llmTasks", + "id": "def-server.RetrieveDocumentationAPI.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + { + "pluginId": "llmTasks", + "scope": "server", + "docId": "kibLlmTasksPluginApi", + "section": "def-server.RetrieveDocumentationParams", + "text": "RetrieveDocumentationParams" + } + ], + "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], "objects": [], "setup": { "parentPluginId": "llmTasks", @@ -75,9 +399,21 @@ ], "signature": [ "(options: ", - "RetrieveDocumentationParams", + { + "pluginId": "llmTasks", + "scope": "server", + "docId": "kibLlmTasksPluginApi", + "section": "def-server.RetrieveDocumentationParams", + "text": "RetrieveDocumentationParams" + }, ") => Promise<", - "RetrieveDocumentationResult", + { + "pluginId": "llmTasks", + "scope": "server", + "docId": "kibLlmTasksPluginApi", + "section": "def-server.RetrieveDocumentationResult", + "text": "RetrieveDocumentationResult" + }, ">" ], "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/types.ts", @@ -93,7 +429,13 @@ "label": "options", "description": [], "signature": [ - "RetrieveDocumentationParams" + { + "pluginId": "llmTasks", + "scope": "server", + "docId": "kibLlmTasksPluginApi", + "section": "def-server.RetrieveDocumentationParams", + "text": "RetrieveDocumentationParams" + } ], "path": "x-pack/platform/plugins/shared/ai_infra/llm_tasks/server/tasks/retrieve_documentation/types.ts", "deprecated": false, diff --git a/api_docs/llm_tasks.mdx b/api_docs/llm_tasks.mdx index c5c671627d267..ccccc5a969f14 100644 --- a/api_docs/llm_tasks.mdx +++ b/api_docs/llm_tasks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/llmTasks title: "llmTasks" image: https://source.unsplash.com/400x175/?github description: API docs for the llmTasks plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'llmTasks'] --- import llmTasksObj from './llm_tasks.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/appex-ai-infra](https://github.com/orgs/elastic/teams/appex-ai | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 5 | 0 | 1 | 2 | +| 24 | 0 | 2 | 0 | ## Server @@ -31,3 +31,9 @@ Contact [@elastic/appex-ai-infra](https://github.com/orgs/elastic/teams/appex-ai ### Start +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/logs_data_access.mdx b/api_docs/logs_data_access.mdx index 1e1b7f1fc9c30..54fac89333487 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: 2025-01-16 +date: 2025-01-21 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 9c02cb60f1986..5bd6445a9e703 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: 2025-01-16 +date: 2025-01-21 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 684da283cb8b1..d6de17119bd61 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: 2025-01-16 +date: 2025-01-21 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 90dc647f36860..a3a85add21f5d 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: 2025-01-16 +date: 2025-01-21 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 81c89611d6a3b..4a2d369f0735b 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: 2025-01-16 +date: 2025-01-21 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 368bbe998c04e..d5d4810975b30 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: 2025-01-16 +date: 2025-01-21 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 029a0fd159f40..942f2ef069bbb 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: 2025-01-16 +date: 2025-01-21 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 803881865e07f..7ce7c19c9c824 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: 2025-01-16 +date: 2025-01-21 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 91b4d4fbe09dc..132dae2531112 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: 2025-01-16 +date: 2025-01-21 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 d3136787509ac..fd0c841bd006d 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: 2025-01-16 +date: 2025-01-21 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 453ef0567b950..2f00c92b6ee3d 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: 2025-01-16 +date: 2025-01-21 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 355d850c2d588..a5fa19eaf0ec4 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: 2025-01-16 +date: 2025-01-21 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 c864ad2cfc96b..b44e9f2f111a7 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: 2025-01-16 +date: 2025-01-21 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 5825c2028ae4a..b151af31e42df 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: 2025-01-16 +date: 2025-01-21 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 3e54cfb7523ce..fb1052c17a32c 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: 2025-01-16 +date: 2025-01-21 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 a352608f8c255..ba1008f830762 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -1008,7 +1008,7 @@ "label": "useAnnotations", "description": [], "signature": [ - "({ domain, editAnnotation, slo, setEditAnnotation, }?: { slo?: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; fiveMinuteBurnRate: number; oneHourBurnRate: number; oneDayBurnRate: number; } & { summaryUpdatedAt?: string | null | undefined; }; groupings: { [x: string]: string | number; }; } & { instanceId?: string | undefined; meta?: { synthetics?: { monitorId: string; locationId: string; configId: string; } | undefined; } | undefined; remote?: { remoteName: string; kibanaUrl: string; } | undefined; }) | undefined; editAnnotation?: ({ id: string; } & { annotation: { title?: string | undefined; type?: string | undefined; style?: { icon?: string | undefined; color?: string | undefined; line?: { width?: number | undefined; style?: \"dashed\" | \"solid\" | \"dotted\" | undefined; iconPosition?: \"top\" | \"bottom\" | undefined; textDecoration?: \"none\" | \"name\" | undefined; } | undefined; rect?: { fill?: \"inside\" | \"outside\" | undefined; } | undefined; } | undefined; }; '@timestamp': string; message: string; } & { event?: ({ start: string; } & { end?: string | undefined; }) | undefined; tags?: string[] | undefined; service?: { name?: string | undefined; environment?: string | undefined; version?: string | undefined; } | undefined; monitor?: { id?: string | undefined; } | undefined; slo?: ({ id: string; } & { instanceId?: string | undefined; }) | undefined; host?: { name?: string | undefined; } | undefined; }) | null | undefined; setEditAnnotation?: ((annotation: ({ id: string; } & { annotation: { title?: string | undefined; type?: string | undefined; style?: { icon?: string | undefined; color?: string | undefined; line?: { width?: number | undefined; style?: \"dashed\" | \"solid\" | \"dotted\" | undefined; iconPosition?: \"top\" | \"bottom\" | undefined; textDecoration?: \"none\" | \"name\" | undefined; } | undefined; rect?: { fill?: \"inside\" | \"outside\" | undefined; } | undefined; } | undefined; }; '@timestamp': string; message: string; } & { event?: ({ start: string; } & { end?: string | undefined; }) | undefined; tags?: string[] | undefined; service?: { name?: string | undefined; environment?: string | undefined; version?: string | undefined; } | undefined; monitor?: { id?: string | undefined; } | undefined; slo?: ({ id: string; } & { instanceId?: string | undefined; }) | undefined; host?: { name?: string | undefined; } | undefined; }) | null) => void) | undefined; domain?: { min: string | number; max: string | number; } | undefined; }) => { annotations: ({ id: string; } & { annotation: { title?: string | undefined; type?: string | undefined; style?: { icon?: string | undefined; color?: string | undefined; line?: { width?: number | undefined; style?: \"dashed\" | \"solid\" | \"dotted\" | undefined; iconPosition?: \"top\" | \"bottom\" | undefined; textDecoration?: \"none\" | \"name\" | undefined; } | undefined; rect?: { fill?: \"inside\" | \"outside\" | undefined; } | undefined; } | undefined; }; '@timestamp': string; message: string; } & { event?: ({ start: string; } & { end?: string | undefined; }) | undefined; tags?: string[] | undefined; service?: { name?: string | undefined; environment?: string | undefined; version?: string | undefined; } | undefined; monitor?: { id?: string | undefined; } | undefined; slo?: ({ id: string; } & { instanceId?: string | undefined; }) | undefined; host?: { name?: string | undefined; } | undefined; })[]; onAnnotationClick: (annotations: { rects: ", + "({ domain, editAnnotation, slo, setEditAnnotation, }?: { slo?: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { createdBy?: string | undefined; updatedBy?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; fiveMinuteBurnRate: number; oneHourBurnRate: number; oneDayBurnRate: number; } & { summaryUpdatedAt?: string | null | undefined; }; groupings: { [x: string]: string | number; }; } & { instanceId?: string | undefined; meta?: { synthetics?: { monitorId: string; locationId: string; configId: string; } | undefined; } | undefined; remote?: { remoteName: string; kibanaUrl: string; } | undefined; }) | undefined; editAnnotation?: ({ id: string; } & { annotation: { title?: string | undefined; type?: string | undefined; style?: { icon?: string | undefined; color?: string | undefined; line?: { width?: number | undefined; style?: \"dashed\" | \"solid\" | \"dotted\" | undefined; iconPosition?: \"top\" | \"bottom\" | undefined; textDecoration?: \"none\" | \"name\" | undefined; } | undefined; rect?: { fill?: \"inside\" | \"outside\" | undefined; } | undefined; } | undefined; }; '@timestamp': string; message: string; } & { event?: ({ start: string; } & { end?: string | undefined; }) | undefined; tags?: string[] | undefined; service?: { name?: string | undefined; environment?: string | undefined; version?: string | undefined; } | undefined; monitor?: { id?: string | undefined; } | undefined; slo?: ({ id: string; } & { instanceId?: string | undefined; }) | undefined; host?: { name?: string | undefined; } | undefined; }) | null | undefined; setEditAnnotation?: ((annotation: ({ id: string; } & { annotation: { title?: string | undefined; type?: string | undefined; style?: { icon?: string | undefined; color?: string | undefined; line?: { width?: number | undefined; style?: \"dashed\" | \"solid\" | \"dotted\" | undefined; iconPosition?: \"top\" | \"bottom\" | undefined; textDecoration?: \"none\" | \"name\" | undefined; } | undefined; rect?: { fill?: \"inside\" | \"outside\" | undefined; } | undefined; } | undefined; }; '@timestamp': string; message: string; } & { event?: ({ start: string; } & { end?: string | undefined; }) | undefined; tags?: string[] | undefined; service?: { name?: string | undefined; environment?: string | undefined; version?: string | undefined; } | undefined; monitor?: { id?: string | undefined; } | undefined; slo?: ({ id: string; } & { instanceId?: string | undefined; }) | undefined; host?: { name?: string | undefined; } | undefined; }) | null) => void) | undefined; domain?: { min: string | number; max: string | number; } | undefined; }) => { annotations: ({ id: string; } & { annotation: { title?: string | undefined; type?: string | undefined; style?: { icon?: string | undefined; color?: string | undefined; line?: { width?: number | undefined; style?: \"dashed\" | \"solid\" | \"dotted\" | undefined; iconPosition?: \"top\" | \"bottom\" | undefined; textDecoration?: \"none\" | \"name\" | undefined; } | undefined; rect?: { fill?: \"inside\" | \"outside\" | undefined; } | undefined; } | undefined; }; '@timestamp': string; message: string; } & { event?: ({ start: string; } & { end?: string | undefined; }) | undefined; tags?: string[] | undefined; service?: { name?: string | undefined; environment?: string | undefined; version?: string | undefined; } | undefined; monitor?: { id?: string | undefined; } | undefined; slo?: ({ id: string; } & { instanceId?: string | undefined; }) | undefined; host?: { name?: string | undefined; } | undefined; })[]; onAnnotationClick: (annotations: { rects: ", "RectAnnotationEvent", "[]; lines: ", "LineAnnotationEvent", @@ -1045,7 +1045,7 @@ "label": "slo", "description": [], "signature": [ - "({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; fiveMinuteBurnRate: number; oneHourBurnRate: number; oneDayBurnRate: number; } & { summaryUpdatedAt?: string | null | undefined; }; groupings: { [x: string]: string | number; }; } & { instanceId?: string | undefined; meta?: { synthetics?: { monitorId: string; locationId: string; configId: string; } | undefined; } | undefined; remote?: { remoteName: string; kibanaUrl: string; } | undefined; }) | undefined" + "({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: 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; }; } & { $state?: any; })[]; }; total: 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; }; } & { $state?: any; })[]; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; }); } & { filter?: 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; }; } & { $state?: any; })[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; } & { syncField?: string | null | undefined; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { createdBy?: string | undefined; updatedBy?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; fiveMinuteBurnRate: number; oneHourBurnRate: number; oneDayBurnRate: number; } & { summaryUpdatedAt?: string | null | undefined; }; groupings: { [x: string]: string | number; }; } & { instanceId?: string | undefined; meta?: { synthetics?: { monitorId: string; locationId: string; configId: string; } | undefined; } | undefined; remote?: { remoteName: string; kibanaUrl: string; } | undefined; }) | undefined" ], "path": "x-pack/solutions/observability/plugins/observability/public/components/annotations/use_annotations.tsx", "deprecated": false, diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 2f6a40fbc6a80..ef3c7c88b646d 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/observability_a_i_assistant.devdocs.json b/api_docs/observability_a_i_assistant.devdocs.json index 4349ba7213743..4df8301201138 100644 --- a/api_docs/observability_a_i_assistant.devdocs.json +++ b/api_docs/observability_a_i_assistant.devdocs.json @@ -8308,7 +8308,7 @@ "label": "chat", "description": [], "signature": [ - "(name: string, { messages, connectorId, functions, functionCall, signal, simulateFunctionCalling, tracer, }: { messages: ", + "(name: string, { messages, connectorId, functions, functionCall, signal, simulateFunctionCalling, tracer, stream, }: { messages: ", { "pluginId": "observabilityAIAssistant", "scope": "common", @@ -8326,7 +8326,7 @@ }, " | undefined; }[] | undefined; functionCall?: string | undefined; signal: AbortSignal; simulateFunctionCalling?: boolean | undefined; tracer: ", "LangTracer", - "; }) => ", + "; stream: TStream; }) => TStream extends true ? ", "Observable", "<", { @@ -8352,7 +8352,23 @@ "section": "def-common.TokenCountEvent", "text": "TokenCountEvent" }, - ">" + "> : Promise<", + { + "pluginId": "@kbn/inference-common", + "scope": "common", + "docId": "kibKbnInferenceCommonPluginApi", + "section": "def-common.ChatCompleteResponse", + "text": "ChatCompleteResponse" + }, + "<", + { + "pluginId": "@kbn/inference-common", + "scope": "common", + "docId": "kibKbnInferenceCommonPluginApi", + "section": "def-common.ToolOptions", + "text": "ToolOptions" + }, + ">>" ], "path": "x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/index.ts", "deprecated": false, @@ -8378,7 +8394,7 @@ "id": "def-server.ObservabilityAIAssistantClient.chat.$2", "type": "Object", "tags": [], - "label": "{\n messages,\n connectorId,\n functions,\n functionCall,\n signal,\n simulateFunctionCalling,\n tracer,\n }", + "label": "{\n messages,\n connectorId,\n functions,\n functionCall,\n signal,\n simulateFunctionCalling,\n tracer,\n stream,\n }", "description": [], "path": "x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/index.ts", "deprecated": false, @@ -8493,6 +8509,20 @@ "path": "x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/index.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "observabilityAIAssistant", + "id": "def-server.ObservabilityAIAssistantClient.chat.$2.stream", + "type": "Uncategorized", + "tags": [], + "label": "stream", + "description": [], + "signature": [ + "TStream" + ], + "path": "x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/index.ts", + "deprecated": false, + "trackAdoption": false } ] } diff --git a/api_docs/observability_a_i_assistant.mdx b/api_docs/observability_a_i_assistant.mdx index 0ef8c6cb3f899..6763df096de87 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistant'] --- import observabilityAIAssistantObj from './observability_a_i_assistant.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 379 | 1 | 377 | 29 | +| 380 | 1 | 378 | 29 | ## Client diff --git a/api_docs/observability_a_i_assistant_app.mdx b/api_docs/observability_a_i_assistant_app.mdx index d39dc40d6165b..d90d278e468c1 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: 2025-01-16 +date: 2025-01-21 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 48898e06740be..dc3d8e8ad9e0a 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: 2025-01-16 +date: 2025-01-21 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 9ee46b95cf3d5..8bde075e8dfa7 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: 2025-01-16 +date: 2025-01-21 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 f04a46e19b1da..5e4dd1333ae2c 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: 2025-01-16 +date: 2025-01-21 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 cee90f34d8cee..2e264b5b7f0aa 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: 2025-01-16 +date: 2025-01-21 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 8b81aef2fbcf9..d1cc2a6043b2d 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: 2025-01-16 +date: 2025-01-21 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 a38a169e0da12..3df9960c4cd1a 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: 2025-01-16 +date: 2025-01-21 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 ff54c53afa7b8..f5677f97b496a 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -21,7 +21,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 54973 | 255 | 41333 | 2707 | +| 55038 | 255 | 41357 | 2707 | ## Plugin Directory @@ -69,7 +69,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | A stateful layer to register shared features and provide an access point to discover without a direct dependency | 26 | 0 | 23 | 2 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | APIs used to assess the quality of data in Elasticsearch indexes | 2 | 0 | 0 | 0 | | | [@elastic/security-generative-ai](https://github.com/orgs/elastic/teams/security-generative-ai) | Server APIs for the Elastic AI Assistant | 55 | 0 | 40 | 2 | -| | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds embeddables service to Kibana | 172 | 0 | 145 | 2 | +| | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds embeddables service to Kibana | 167 | 0 | 140 | 2 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Extends embeddable plugin with more functionality | 15 | 0 | 15 | 2 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides encryption and decryption utilities for saved objects containing sensitive information. | 54 | 0 | 47 | 1 | | | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | Adds dashboards for discovering and managing Enterprise Search products. | 5 | 0 | 5 | 0 | @@ -85,7 +85,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 127 | 0 | 127 | 12 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'error' renderer to expressions | 17 | 0 | 15 | 2 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Expression Gauge plugin adds a `gauge` renderer and function to the expression plugin. The renderer will display the `gauge` chart. | 59 | 0 | 58 | 2 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Expression Heatmap plugin adds a `heatmap` renderer and function to the expression plugin. The renderer will display the `heatmap` chart. | 112 | 0 | 108 | 2 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Expression Heatmap plugin adds a `heatmap` renderer and function to the expression plugin. The renderer will display the `heatmap` chart. | 115 | 0 | 111 | 2 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'image' function and renderer to expressions | 26 | 0 | 26 | 0 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Adds a `metric` renderer and function to the expression plugin. The renderer will display the `legacy metric` chart. | 51 | 0 | 51 | 2 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'metric' function and renderer to expressions | 32 | 0 | 27 | 0 | @@ -97,13 +97,13 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Expression Tagcloud plugin adds a `tagcloud` renderer and function to the expression plugin. The renderer will display the `Wordcloud` chart. | 6 | 0 | 6 | 2 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Expression XY plugin adds a `xy` renderer and function to the expression plugin. The renderer will display the `xy` chart. | 182 | 0 | 171 | 13 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Adds expression runtime to Kibana | 2241 | 17 | 1769 | 6 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 270 | 0 | 110 | 3 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 273 | 0 | 109 | 3 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Index pattern fields and ambiguous values formatters | 293 | 5 | 254 | 3 | | | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | Exposes services for async usage and search of fields metadata. | 45 | 0 | 45 | 9 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON. | 89 | 0 | 89 | 8 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | File upload, download, sharing, and serving over HTTP implementation in Kibana. | 240 | 0 | 24 | 9 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Simple UI for managing files in Kibana | 3 | 0 | 3 | 0 | -| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1446 | 5 | 1319 | 82 | +| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1448 | 5 | 1321 | 84 | | ftrApis | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 72 | 0 | 14 | 5 | | globalSearchBar | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 0 | 0 | 0 | 0 | @@ -136,7 +136,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 119 | 0 | 42 | 10 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | A dashboard panel for creating links to dashboards or external links. | 5 | 0 | 5 | 0 | | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 227 | 0 | 98 | 52 | -| | [@elastic/appex-ai-infra](https://github.com/orgs/elastic/teams/appex-ai-infra) | - | 5 | 0 | 1 | 2 | +| | [@elastic/appex-ai-infra](https://github.com/orgs/elastic/teams/appex-ai-infra) | - | 24 | 0 | 2 | 0 | | | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | - | 15 | 0 | 13 | 7 | | | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | This plugin provides a LogsExplorer component using the Discover customization framework, offering several affordances specifically designed for log consumption. | 119 | 4 | 119 | 22 | | | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | Exposes the shared components and APIs to access and visualize logs. | 256 | 0 | 230 | 33 | @@ -154,7 +154,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 3 | 0 | 3 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 2 | 0 | 2 | 1 | | | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 697 | 2 | 689 | 23 | -| | [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai-assistant) | - | 379 | 1 | 377 | 29 | +| | [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai-assistant) | - | 380 | 1 | 378 | 29 | | | [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai-assistant) | - | 8 | 0 | 7 | 0 | | | [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai-assistant) | - | 2 | 0 | 2 | 0 | | | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | This plugin exposes and registers observability log consumption features. | 3 | 0 | 3 | 0 | @@ -163,8 +163,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/security-defend-workflows](https://github.com/orgs/elastic/teams/security-defend-workflows) | - | 23 | 0 | 23 | 7 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 2 | 0 | 2 | 0 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds a standardized Presentation panel which allows any forward ref component to interface with various Kibana systems. | 9 | 0 | 9 | 4 | -| | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Presentation Utility Plugin is a set of common, shared components and toolkits for solutions within the Presentation space, (e.g. Dashboards, Canvas). | 126 | 2 | 102 | 8 | -| | [@elastic/appex-ai-infra](https://github.com/orgs/elastic/teams/appex-ai-infra) | - | 10 | 0 | 10 | 4 | +| | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Presentation Utility Plugin is a set of common, shared components and toolkits for solutions within the Presentation space, (e.g. Dashboards, Canvas). | 124 | 2 | 100 | 7 | +| | [@elastic/appex-ai-infra](https://github.com/orgs/elastic/teams/appex-ai-infra) | - | 23 | 0 | 9 | 2 | | | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 16 | 1 | 16 | 0 | | | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 22 | 0 | 22 | 7 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 23 | 0 | 23 | 0 | @@ -191,7 +191,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | - | 5 | 0 | 5 | 0 | | searchprofiler | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 0 | 0 | 0 | 0 | | | [@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. | 461 | 0 | 238 | 0 | -| | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | - | 191 | 0 | 123 | 34 | +| | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | - | 193 | 0 | 125 | 35 | | | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | ESS customizations for Security Solution. | 6 | 0 | 6 | 0 | | | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | Serverless customizations for security. | 7 | 0 | 7 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | The core Serverless plugin, providing APIs to Serverless Project plugins. | 25 | 0 | 24 | 0 | @@ -207,12 +207,12 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/streams-program-team](https://github.com/orgs/elastic/teams/streams-program-team) | A manager for Streams | 13 | 0 | 13 | 13 | | | [@elastic/streams-program-team](https://github.com/orgs/elastic/teams/streams-program-team) | - | 8 | 0 | 8 | 0 | | synthetics | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | This plugin visualizes data from Synthetics and Heartbeat, and integrates with other Observability solutions. | 0 | 0 | 0 | 0 | -| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 104 | 0 | 61 | 7 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 45 | 0 | 1 | 0 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 105 | 0 | 62 | 7 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 47 | 0 | 1 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 31 | 0 | 26 | 6 | | telemetryCollectionXpack | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 6 | 0 | 0 | 0 | -| | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | Elastic threat intelligence helps you see if you are open to or have been subject to current or historical known threats | 30 | 0 | 14 | 4 | +| | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | Elastic threat intelligence helps you see if you are open to or have been subject to current or historical known threats | 31 | 0 | 14 | 4 | | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | - | 236 | 1 | 192 | 18 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the transforms features provided by Elastic. Transforms enable you to convert existing Elasticsearch indices into summarized indices, which provide opportunities for new insights and analytics. | 4 | 0 | 4 | 1 | | translations | [@elastic/kibana-localization](https://github.com/orgs/elastic/teams/kibana-localization) | - | 0 | 0 | 0 | 0 | @@ -379,9 +379,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 22 | 0 | 7 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 9 | 0 | 9 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 7 | 0 | 7 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 54 | 7 | 54 | 0 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 57 | 7 | 57 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 15 | 0 | 15 | 1 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 568 | 2 | 243 | 0 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 569 | 2 | 243 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 96 | 0 | 83 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 46 | 0 | 45 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 6 | 0 | 2 | 0 | @@ -494,7 +494,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 52 | 0 | 52 | 1 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 19 | 0 | 14 | 0 | | | [@elastic/security-threat-hunting](https://github.com/orgs/elastic/teams/security-threat-hunting) | - | 55 | 0 | 54 | 0 | -| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 7 | 0 | 5 | 0 | +| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 8 | 0 | 6 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 44 | 0 | 43 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 7 | 0 | 7 | 0 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 5 | 0 | 5 | 0 | @@ -540,7 +540,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 22 | 0 | 18 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 51 | 0 | 42 | 2 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 2 | 0 | 0 | 0 | -| | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 111 | 2 | 86 | 1 | +| | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 114 | 2 | 89 | 1 | | | [@elastic/appex-qa](https://github.com/orgs/elastic/teams/appex-qa) | - | 564 | 6 | 524 | 7 | | | [@elastic/appex-ai-infra](https://github.com/orgs/elastic/teams/appex-ai-infra) | - | 10 | 0 | 8 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 1 | 0 | 0 | 0 | @@ -560,7 +560,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/security-threat-hunting](https://github.com/orgs/elastic/teams/security-threat-hunting) | - | 85 | 0 | 80 | 2 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 78 | 0 | 76 | 0 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 126 | 3 | 126 | 0 | -| | [@elastic/appex-ai-infra](https://github.com/orgs/elastic/teams/appex-ai-infra) | - | 160 | 0 | 55 | 4 | +| | [@elastic/appex-ai-infra](https://github.com/orgs/elastic/teams/appex-ai-infra) | - | 161 | 0 | 55 | 4 | | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 88 | 0 | 88 | 0 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 7 | 1 | 7 | 1 | | | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 9 | 0 | 9 | 0 | @@ -696,7 +696,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | - | 8 | 0 | 8 | 1 | | | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | - | 3 | 0 | 3 | 0 | | | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | - | 76 | 0 | 76 | 0 | -| | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | - | 3954 | 0 | 3954 | 0 | +| | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | - | 3956 | 0 | 3956 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 18 | 1 | 17 | 1 | | | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | - | 36 | 0 | 34 | 3 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 20 | 0 | 18 | 1 | @@ -712,14 +712,14 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 282 | 1 | 161 | 0 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 74 | 0 | 73 | 0 | | | [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) | - | 7 | 0 | 0 | 0 | -| | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 15 | 0 | 15 | 7 | +| | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 17 | 0 | 17 | 9 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 54 | 0 | 49 | 0 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 29 | 0 | 23 | 0 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 2 | 0 | 0 | 0 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 47 | 0 | 12 | 0 | | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 56 | 1 | 41 | 0 | | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | - | 92 | 0 | 70 | 6 | -| | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 341 | 1 | 337 | 32 | +| | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 353 | 1 | 349 | 32 | | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 91 | 0 | 78 | 1 | | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 107 | 0 | 96 | 1 | | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 15 | 0 | 7 | 0 | diff --git a/api_docs/presentation_panel.mdx b/api_docs/presentation_panel.mdx index 540927aa41d12..9225820d6ac2f 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationPanel'] --- import presentationPanelObj from './presentation_panel.devdocs.json'; diff --git a/api_docs/presentation_util.devdocs.json b/api_docs/presentation_util.devdocs.json index e08e196fc1845..66b10c923dbb2 100644 --- a/api_docs/presentation_util.devdocs.json +++ b/api_docs/presentation_util.devdocs.json @@ -37,41 +37,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "presentationUtil", - "id": "def-public.FloatingActions", - "type": "Function", - "tags": [], - "label": "FloatingActions", - "description": [], - "signature": [ - "({ children, viewMode, isEnabled, api, className, disabledActions, }: ", - "FloatingActionsProps", - ") => React.JSX.Element" - ], - "path": "src/platform/plugins/shared/presentation_util/public/components/floating_actions/floating_actions.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "presentationUtil", - "id": "def-public.FloatingActions.$1", - "type": "Object", - "tags": [], - "label": "{\n children,\n viewMode,\n isEnabled,\n api,\n className = '',\n disabledActions,\n}", - "description": [], - "signature": [ - "FloatingActionsProps" - ], - "path": "src/platform/plugins/shared/presentation_util/public/components/floating_actions/floating_actions.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "presentationUtil", "id": "def-public.LazyDashboardPicker", diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index a9793058d57cb..e2d4fe7dfc0d3 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kib | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 126 | 2 | 102 | 8 | +| 124 | 2 | 100 | 7 | ## Client diff --git a/api_docs/product_doc_base.devdocs.json b/api_docs/product_doc_base.devdocs.json index 71ded441b875c..4ad874b496ff7 100644 --- a/api_docs/product_doc_base.devdocs.json +++ b/api_docs/product_doc_base.devdocs.json @@ -54,7 +54,211 @@ "server": { "classes": [], "functions": [], - "interfaces": [], + "interfaces": [ + { + "parentPluginId": "productDocBase", + "id": "def-server.DocSearchOptions", + "type": "Interface", + "tags": [], + "label": "DocSearchOptions", + "description": [ + "\nOptions for the Product documentation {@link SearchApi}" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/search/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "productDocBase", + "id": "def-server.DocSearchOptions.query", + "type": "string", + "tags": [], + "label": "query", + "description": [ + "plain text search query" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/search/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "productDocBase", + "id": "def-server.DocSearchOptions.max", + "type": "number", + "tags": [], + "label": "max", + "description": [ + "max number of hits. Defaults to 3" + ], + "signature": [ + "number | undefined" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/search/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "productDocBase", + "id": "def-server.DocSearchOptions.highlights", + "type": "number", + "tags": [], + "label": "highlights", + "description": [ + "number of content highlights per hit. Defaults to 3" + ], + "signature": [ + "number | undefined" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/search/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "productDocBase", + "id": "def-server.DocSearchOptions.products", + "type": "Array", + "tags": [], + "label": "products", + "description": [ + "optional list of products to filter search" + ], + "signature": [ + "(\"security\" | \"kibana\" | \"observability\" | \"elasticsearch\")[] | undefined" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/search/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "productDocBase", + "id": "def-server.DocSearchResponse", + "type": "Interface", + "tags": [], + "label": "DocSearchResponse", + "description": [ + "\nResponse for the {@link SearchApi}" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/search/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "productDocBase", + "id": "def-server.DocSearchResponse.results", + "type": "Array", + "tags": [], + "label": "results", + "description": [ + "List of results for this search" + ], + "signature": [ + { + "pluginId": "productDocBase", + "scope": "server", + "docId": "kibProductDocBasePluginApi", + "section": "def-server.DocSearchResult", + "text": "DocSearchResult" + }, + "[]" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/search/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "productDocBase", + "id": "def-server.DocSearchResult", + "type": "Interface", + "tags": [], + "label": "DocSearchResult", + "description": [ + "\nIndividual result returned in a {@link DocSearchResponse} by the {@link SearchApi}" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/search/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "productDocBase", + "id": "def-server.DocSearchResult.title", + "type": "string", + "tags": [], + "label": "title", + "description": [ + "title of the doc article page" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/search/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "productDocBase", + "id": "def-server.DocSearchResult.url", + "type": "string", + "tags": [], + "label": "url", + "description": [ + "full url to the online documentation" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/search/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "productDocBase", + "id": "def-server.DocSearchResult.productName", + "type": "CompoundType", + "tags": [], + "label": "productName", + "description": [ + "product name this document is associated to" + ], + "signature": [ + "\"security\" | \"kibana\" | \"observability\" | \"elasticsearch\"" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/search/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "productDocBase", + "id": "def-server.DocSearchResult.content", + "type": "string", + "tags": [], + "label": "content", + "description": [ + "full content of the doc article" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/search/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "productDocBase", + "id": "def-server.DocSearchResult.highlights", + "type": "Array", + "tags": [], + "label": "highlights", + "description": [ + "content highlights based on the query" + ], + "signature": [ + "string[]" + ], + "path": "x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/search/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], "enums": [], "misc": [ { @@ -63,12 +267,26 @@ "type": "Type", "tags": [], "label": "SearchApi", - "description": [], + "description": [ + "\nSearch API to be used to retrieve product documentation." + ], "signature": [ "(options: ", - "DocSearchOptions", + { + "pluginId": "productDocBase", + "scope": "server", + "docId": "kibProductDocBasePluginApi", + "section": "def-server.DocSearchOptions", + "text": "DocSearchOptions" + }, ") => Promise<", - "DocSearchResponse", + { + "pluginId": "productDocBase", + "scope": "server", + "docId": "kibProductDocBasePluginApi", + "section": "def-server.DocSearchResponse", + "text": "DocSearchResponse" + }, ">" ], "path": "x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/search/types.ts", @@ -84,7 +302,13 @@ "label": "options", "description": [], "signature": [ - "DocSearchOptions" + { + "pluginId": "productDocBase", + "scope": "server", + "docId": "kibProductDocBasePluginApi", + "section": "def-server.DocSearchOptions", + "text": "DocSearchOptions" + } ], "path": "x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/search/types.ts", "deprecated": false, @@ -129,9 +353,21 @@ "description": [], "signature": [ "(options: ", - "DocSearchOptions", + { + "pluginId": "productDocBase", + "scope": "server", + "docId": "kibProductDocBasePluginApi", + "section": "def-server.DocSearchOptions", + "text": "DocSearchOptions" + }, ") => Promise<", - "DocSearchResponse", + { + "pluginId": "productDocBase", + "scope": "server", + "docId": "kibProductDocBasePluginApi", + "section": "def-server.DocSearchResponse", + "text": "DocSearchResponse" + }, ">" ], "path": "x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/types.ts", @@ -147,7 +383,13 @@ "label": "options", "description": [], "signature": [ - "DocSearchOptions" + { + "pluginId": "productDocBase", + "scope": "server", + "docId": "kibProductDocBasePluginApi", + "section": "def-server.DocSearchOptions", + "text": "DocSearchOptions" + } ], "path": "x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/search/types.ts", "deprecated": false, diff --git a/api_docs/product_doc_base.mdx b/api_docs/product_doc_base.mdx index 7acbac7ca1ccb..7ac849155e8c2 100644 --- a/api_docs/product_doc_base.mdx +++ b/api_docs/product_doc_base.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/productDocBase title: "productDocBase" image: https://source.unsplash.com/400x175/?github description: API docs for the productDocBase plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'productDocBase'] --- import productDocBaseObj from './product_doc_base.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/appex-ai-infra](https://github.com/orgs/elastic/teams/appex-ai | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 10 | 0 | 10 | 4 | +| 23 | 0 | 9 | 2 | ## Client @@ -39,6 +39,9 @@ Contact [@elastic/appex-ai-infra](https://github.com/orgs/elastic/teams/appex-ai ### Start +### Interfaces + + ### Consts, variables and types diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index b9620d8071aa6..c12c4c65fa1c4 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: 2025-01-16 +date: 2025-01-21 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 38392a4f45b5b..61551e852a350 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: 2025-01-16 +date: 2025-01-21 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 f1d8e59b00ad8..b560b00c75ff2 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: 2025-01-16 +date: 2025-01-21 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 13fe851db5d21..8c02c169b682c 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: 2025-01-16 +date: 2025-01-21 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 da1aeed741790..99690584b388d 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: 2025-01-16 +date: 2025-01-21 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 75175497eea6c..8169728a794c0 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: 2025-01-16 +date: 2025-01-21 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 4a6b95371d859..4a47afce2f3aa 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: 2025-01-16 +date: 2025-01-21 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 df3264974f364..1fdf6b26e4e51 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: 2025-01-16 +date: 2025-01-21 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 42dfb7845dc49..a5d32f07005ac 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: 2025-01-16 +date: 2025-01-21 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 81eec142820ae..8ae493703e3a8 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: 2025-01-16 +date: 2025-01-21 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 604c9b74a0e10..4b17aa6ed79ca 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: 2025-01-16 +date: 2025-01-21 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 f4a0f3266b7a6..8bafb2aaaa871 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: 2025-01-16 +date: 2025-01-21 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 f304c3482dee2..fe69e9f50331b 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: 2025-01-16 +date: 2025-01-21 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 d49cff85eaaf5..f4acebc11850b 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: 2025-01-16 +date: 2025-01-21 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 9ac3ce2cf503a..5407be439fd71 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/search_assistant.mdx b/api_docs/search_assistant.mdx index 757ec14075f78..0cddc7bf61ca1 100644 --- a/api_docs/search_assistant.mdx +++ b/api_docs/search_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchAssistant title: "searchAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the searchAssistant plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchAssistant'] --- import searchAssistantObj from './search_assistant.devdocs.json'; diff --git a/api_docs/search_connectors.mdx b/api_docs/search_connectors.mdx index 622d06028fc40..e5349a83a86b5 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: 2025-01-16 +date: 2025-01-21 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 9b40517ed589e..e39cd6df256b1 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchHomepage'] --- import searchHomepageObj from './search_homepage.devdocs.json'; diff --git a/api_docs/search_indices.mdx b/api_docs/search_indices.mdx index 8a6626f94d0e6..f72e4e584262d 100644 --- a/api_docs/search_indices.mdx +++ b/api_docs/search_indices.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchIndices title: "searchIndices" image: https://source.unsplash.com/400x175/?github description: API docs for the searchIndices plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchIndices'] --- import searchIndicesObj from './search_indices.devdocs.json'; diff --git a/api_docs/search_inference_endpoints.mdx b/api_docs/search_inference_endpoints.mdx index 339d1d51cce10..cb20ccd57d87e 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchInferenceEndpoints'] --- import searchInferenceEndpointsObj from './search_inference_endpoints.devdocs.json'; diff --git a/api_docs/search_navigation.mdx b/api_docs/search_navigation.mdx index fdfd2d8bfad5d..a57135fdaa8b5 100644 --- a/api_docs/search_navigation.mdx +++ b/api_docs/search_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchNavigation title: "searchNavigation" image: https://source.unsplash.com/400x175/?github description: API docs for the searchNavigation plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchNavigation'] --- import searchNavigationObj from './search_navigation.devdocs.json'; diff --git a/api_docs/search_notebooks.mdx b/api_docs/search_notebooks.mdx index deefe6a103a33..7308765f1ffef 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: 2025-01-16 +date: 2025-01-21 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 c67eac84a4653..6bb0387e768f3 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchPlayground'] --- import searchPlaygroundObj from './search_playground.devdocs.json'; diff --git a/api_docs/search_synonyms.mdx b/api_docs/search_synonyms.mdx index 402ecda530a85..1a97bec02dd69 100644 --- a/api_docs/search_synonyms.mdx +++ b/api_docs/search_synonyms.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchSynonyms title: "searchSynonyms" image: https://source.unsplash.com/400x175/?github description: API docs for the searchSynonyms plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchSynonyms'] --- import searchSynonymsObj from './search_synonyms.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index 7d9d2dc8100a0..c598c2d2fed28 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.devdocs.json b/api_docs/security_solution.devdocs.json index 85267d0c350ee..ca6862ff2c67a 100644 --- a/api_docs/security_solution.devdocs.json +++ b/api_docs/security_solution.devdocs.json @@ -2938,6 +2938,23 @@ "trackAdoption": false, "children": [], "returnComment": [] + }, + { + "parentPluginId": "securitySolution", + "id": "def-server.SecuritySolutionApiRequestHandlerContext.getAssetInventoryClient", + "type": "Function", + "tags": [], + "label": "getAssetInventoryClient", + "description": [], + "signature": [ + "() => ", + "AssetInventoryDataClient" + ], + "path": "x-pack/solutions/security/plugins/security_solution/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] } ], "initialIsOpen": false @@ -3223,6 +3240,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "securitySolution", + "id": "def-common.SECURITY_FEATURE_ID", + "type": "string", + "tags": [], + "label": "SECURITY_FEATURE_ID", + "description": [], + "signature": [ + "\"siemV2\"" + ], + "path": "x-pack/solutions/security/plugins/security_solution/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "securitySolution", "id": "def-common.SENTINEL_ONE_ACTIVITY_INDEX_PATTERN", diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 74902e11e0b24..7151b4899187d 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-solution](https://github.com/orgs/elastic/teams/secur | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 191 | 0 | 123 | 34 | +| 193 | 0 | 125 | 35 | ## Client diff --git a/api_docs/security_solution_ess.mdx b/api_docs/security_solution_ess.mdx index dfab18954ac0f..857b6deba8702 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: 2025-01-16 +date: 2025-01-21 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 19e90f78cf4ae..7513012024d9d 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: 2025-01-16 +date: 2025-01-21 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 04bcf78144401..26d60941ed2c7 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: 2025-01-16 +date: 2025-01-21 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 08851af6e4e18..1e65edc618c88 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: 2025-01-16 +date: 2025-01-21 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 22584c4c5045f..e729b495cc3cd 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: 2025-01-16 +date: 2025-01-21 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 a2b27f039d32e..d765e61c5a77c 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: 2025-01-16 +date: 2025-01-21 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 f0eed1ed1b623..9909329d46357 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: 2025-01-16 +date: 2025-01-21 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 d4d2b54754bb6..04123974ce1a0 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: 2025-01-16 +date: 2025-01-21 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 b1a0625b1c351..58de98555fba8 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: 2025-01-16 +date: 2025-01-21 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 232f6728c211f..199ac4236cb4a 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: 2025-01-16 +date: 2025-01-21 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 16c032845b330..bac1b3236341b 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: 2025-01-16 +date: 2025-01-21 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 714b3cba26a60..ecde202e00d5e 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/streams.devdocs.json b/api_docs/streams.devdocs.json index b20f84e6cfd7e..81a6c1a09e585 100644 --- a/api_docs/streams.devdocs.json +++ b/api_docs/streams.devdocs.json @@ -63,17 +63,7 @@ "section": "def-common.RouteRepositoryClient", "text": "RouteRepositoryClient" }, - "<{ \"POST /api/streams/{id}/schema/fields_simulation\": ", - { - "pluginId": "@kbn/server-route-repository-utils", - "scope": "common", - "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", - "section": "def-common.ServerRoute", - "text": "ServerRoute" - }, - "<\"POST /api/streams/{id}/schema/fields_simulation\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; body: Zod.ZodObject<{ field_definitions: Zod.ZodArray; format: Zod.ZodOptional; }, { name: Zod.ZodString; }>, \"strip\", Zod.ZodTypeAny, { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }, { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }>, \"many\">; }, \"strip\", Zod.ZodTypeAny, { field_definitions: { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }[]; }, { field_definitions: { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }[]; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; body: { field_definitions: { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }[]; }; }, { path: { id: string; }; body: { field_definitions: { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }[]; }; }>, ", - "StreamsRouteHandlerResources", - ", { status: \"unknown\" | \"success\" | \"failure\"; simulationError: string | null; documentsWithRuntimeFieldsApplied: unknown[] | null; }, undefined>; \"POST /api/streams/{id}/processing/_simulate\": ", + "<{ \"POST /api/streams/{id}/processing/_simulate\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -147,7 +137,7 @@ }, "; }[]; }; }>, ", "StreamsRouteHandlerResources", - ", { documents: { value: Record; isMatch: boolean; }[]; success_rate: number; failure_rate: number; detected_fields: { name: string; type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\" | \"unmapped\"; }[]; }, undefined>; \"GET /api/streams/{id}/schema/unmapped_fields\": ", + ", { documents: { value: Record; isMatch: boolean; }[]; success_rate: number; failure_rate: number; detected_fields: { name: string; type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\" | \"unmapped\"; }[]; }, undefined>; \"POST /api/streams/{id}/schema/fields_simulation\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -155,9 +145,9 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"GET /api/streams/{id}/schema/unmapped_fields\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; }, { path: { id: string; }; }>, ", + "<\"POST /api/streams/{id}/schema/fields_simulation\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; body: Zod.ZodObject<{ field_definitions: Zod.ZodArray; format: Zod.ZodOptional; }, { name: Zod.ZodString; }>, \"strip\", Zod.ZodTypeAny, { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }, { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }>, \"many\">; }, \"strip\", Zod.ZodTypeAny, { field_definitions: { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }[]; }, { field_definitions: { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }[]; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; body: { field_definitions: { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }[]; }; }, { path: { id: string; }; body: { field_definitions: { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }[]; }; }>, ", "StreamsRouteHandlerResources", - ", { unmappedFields: string[]; }, undefined>; \"GET /api/streams/{id}/_details\": ", + ", { status: \"unknown\" | \"success\" | \"failure\"; simulationError: string | null; documentsWithRuntimeFieldsApplied: unknown[] | null; }, undefined>; \"GET /api/streams/{id}/schema/unmapped_fields\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -165,11 +155,9 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"GET /api/streams/{id}/_details\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; query: Zod.ZodObject<{ start: Zod.ZodString; end: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { start: string; end: string; }, { start: string; end: string; }>; }, \"strip\", Zod.ZodTypeAny, { query: { start: string; end: string; }; path: { id: string; }; }, { query: { start: string; end: string; }; path: { id: string; }; }>, ", + "<\"GET /api/streams/{id}/schema/unmapped_fields\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; }, { path: { id: string; }; }>, ", "StreamsRouteHandlerResources", - ", ", - "StreamDetailsResponse", - ", undefined>; \"POST /api/streams/{id}/_sample\": ", + ", { unmappedFields: string[]; }, undefined>; \"POST /api/streams/{id}/_sample\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -227,55 +215,11 @@ }, "; }; }>, ", "StreamsRouteHandlerResources", - ", { documents: unknown[]; }, undefined>; \"POST /api/streams/{id}/dashboards/_bulk\": ", - { - "pluginId": "@kbn/server-route-repository-utils", - "scope": "common", - "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", - "section": "def-common.ServerRoute", - "text": "ServerRoute" - }, - "<\"POST /api/streams/{id}/dashboards/_bulk\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; body: Zod.ZodObject<{ operations: Zod.ZodArray; }, \"strip\", Zod.ZodTypeAny, { index: { id: string; }; }, { index: { id: string; }; }>, Zod.ZodObject<{ delete: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; }, \"strip\", Zod.ZodTypeAny, { delete: { id: string; }; }, { delete: { id: string; }; }>]>, \"many\">; }, \"strip\", Zod.ZodTypeAny, { operations: ({ index: { id: string; }; } | { delete: { id: string; }; })[]; }, { operations: ({ index: { id: string; }; } | { delete: { id: string; }; })[]; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; body: { operations: ({ index: { id: string; }; } | { delete: { id: string; }; })[]; }; }, { path: { id: string; }; body: { operations: ({ index: { id: string; }; } | { delete: { id: string; }; })[]; }; }>, ", - "StreamsRouteHandlerResources", - ", ", - "BulkUpdateAssetsResponse", - ", undefined>; \"POST /api/streams/{id}/dashboards/_suggestions\": ", - { - "pluginId": "@kbn/server-route-repository-utils", - "scope": "common", - "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", - "section": "def-common.ServerRoute", - "text": "ServerRoute" - }, - "<\"POST /api/streams/{id}/dashboards/_suggestions\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; query: Zod.ZodObject<{ query: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { query: string; }, { query: string; }>; body: Zod.ZodObject<{ tags: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { tags?: string[] | undefined; }, { tags?: string[] | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { query: { query: string; }; path: { id: string; }; body: { tags?: string[] | undefined; }; }, { query: { query: string; }; path: { id: string; }; body: { tags?: string[] | undefined; }; }>, ", - "StreamsRouteHandlerResources", - ", ", - "SuggestDashboardResponse", - ", undefined>; \"DELETE /api/streams/{id}/dashboards/{dashboardId}\": ", - { - "pluginId": "@kbn/server-route-repository-utils", - "scope": "common", - "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", - "section": "def-common.ServerRoute", - "text": "ServerRoute" - }, - "<\"DELETE /api/streams/{id}/dashboards/{dashboardId}\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; dashboardId: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; dashboardId: string; }, { id: string; dashboardId: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; dashboardId: string; }; }, { path: { id: string; dashboardId: string; }; }>, ", - "StreamsRouteHandlerResources", - ", ", - "UnlinkDashboardResponse", - ", undefined>; \"PUT /api/streams/{id}/dashboards/{dashboardId}\": ", - { - "pluginId": "@kbn/server-route-repository-utils", - "scope": "common", - "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", - "section": "def-common.ServerRoute", - "text": "ServerRoute" - }, - "<\"PUT /api/streams/{id}/dashboards/{dashboardId}\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; dashboardId: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; dashboardId: string; }, { id: string; dashboardId: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; dashboardId: string; }; }, { path: { id: string; dashboardId: string; }; }>, ", + ", { documents: unknown[]; }, undefined>; \"GET /api/streams/_status\": { endpoint: \"GET /api/streams/_status\"; handler: ServerRouteHandler<", "StreamsRouteHandlerResources", - ", ", - "LinkDashboardResponse", - ", undefined>; \"GET /api/streams/{id}/dashboards\": ", + ", undefined, { enabled: boolean; }>; security?: ", + "RouteSecurity", + " | undefined; }; \"POST /api/streams/_resync\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -283,11 +227,11 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"GET /api/streams/{id}/dashboards\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; }, { path: { id: string; }; }>, ", + "<\"POST /api/streams/_resync\", Zod.ZodObject<{}, \"strip\", Zod.ZodTypeAny, {}, {}>, ", "StreamsRouteHandlerResources", ", ", - "ListDashboardsResponse", - ", undefined>; \"POST /api/streams/_disable\": ", + "ResyncStreamsResponse", + ", undefined>; \"POST /api/streams/{id}/_fork\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -295,37 +239,23 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"POST /api/streams/_disable\", Zod.ZodObject<{}, \"strip\", Zod.ZodTypeAny, {}, {}>, ", - "StreamsRouteHandlerResources", - ", ", - "DisableStreamsResponse", - ", undefined>; \"POST /internal/streams/esql\": ", + "<\"POST /api/streams/{id}/_fork\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; body: Zod.ZodObject<{ stream: Zod.ZodObject<{ name: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { name: string; }, { name: string; }>; condition: Zod.ZodType<", { - "pluginId": "@kbn/server-route-repository-utils", + "pluginId": "@kbn/streams-schema", "scope": "common", - "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", - "section": "def-common.ServerRoute", - "text": "ServerRoute" + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.Condition", + "text": "Condition" }, - "<\"POST /internal/streams/esql\", Zod.ZodObject<{ body: Zod.ZodObject<{ query: Zod.ZodString; operationName: Zod.ZodString; filter: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">>>; kuery: Zod.ZodOptional; start: Zod.ZodOptional; end: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { query: string; operationName: string; start?: number | undefined; end?: number | undefined; filter?: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\"> | undefined; kuery?: string | undefined; }, { query: string; operationName: string; start?: number | undefined; end?: number | undefined; filter?: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\"> | undefined; kuery?: string | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { body: { query: string; operationName: string; start?: number | undefined; end?: number | undefined; filter?: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\"> | undefined; kuery?: string | undefined; }; }, { body: { query: string; operationName: string; start?: number | undefined; end?: number | undefined; filter?: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\"> | undefined; kuery?: string | undefined; }; }>, ", - "StreamsRouteHandlerResources", - ", ", - "UnparsedEsqlResponse", - ", undefined>; \"GET /api/streams/_status\": { endpoint: \"GET /api/streams/_status\"; handler: ServerRouteHandler<", - "StreamsRouteHandlerResources", - ", undefined, { enabled: boolean; }>; security?: ", - "RouteSecurity", - " | undefined; }; \"GET /api/streams\": ", + ", Zod.ZodTypeDef, ", { - "pluginId": "@kbn/server-route-repository-utils", + "pluginId": "@kbn/streams-schema", "scope": "common", - "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", - "section": "def-common.ServerRoute", - "text": "ServerRoute" + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.Condition", + "text": "Condition" }, - "<\"GET /api/streams\", Zod.ZodObject<{}, \"strip\", Zod.ZodTypeAny, {}, {}>, ", - "StreamsRouteHandlerResources", - ", { streams: ({ name: string; stream: { ingest: { routing: { name: string; condition?: ", + ">; }, \"strip\", Zod.ZodTypeAny, { stream: { name: string; }; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -333,7 +263,7 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }[]; processing: { config: { grok: { field: string; patterns: string[]; pattern_definitions?: Record | undefined; ignore_failure?: boolean | undefined; ignore_missing?: boolean | undefined; }; } | { dissect: { field: string; pattern: string; ignore_failure?: boolean | undefined; ignore_missing?: boolean | undefined; append_separator?: string | undefined; }; }; condition?: ", + "; }, { stream: { name: string; }; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -341,7 +271,7 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }[]; wired: { fields: Record; }; }; }; dashboards?: string[] | undefined; elasticsearch_assets?: { id: string; type: \"ingest_pipeline\" | \"data_stream\" | \"index_template\" | \"component_template\"; }[] | undefined; } | { name: string; stream: { ingest: { routing: { name: string; condition?: ", + "; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; body: { stream: { name: string; }; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -349,7 +279,7 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }[]; processing: { config: { grok: { field: string; patterns: string[]; pattern_definitions?: Record | undefined; ignore_failure?: boolean | undefined; ignore_missing?: boolean | undefined; }; } | { dissect: { field: string; pattern: string; ignore_failure?: boolean | undefined; ignore_missing?: boolean | undefined; append_separator?: string | undefined; }; }; condition?: ", + "; }; }, { path: { id: string; }; body: { stream: { name: string; }; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -357,7 +287,33 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }[]; }; }; dashboards?: string[] | undefined; elasticsearch_assets?: { id: string; type: \"ingest_pipeline\" | \"data_stream\" | \"index_template\" | \"component_template\"; }[] | undefined; })[]; }, undefined>; \"DELETE /api/streams/{id}\": ", + "; }; }>, ", + "StreamsRouteHandlerResources", + ", { acknowledged: true; }, undefined>; \"POST /api/streams/_disable\": ", + { + "pluginId": "@kbn/server-route-repository-utils", + "scope": "common", + "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", + "section": "def-common.ServerRoute", + "text": "ServerRoute" + }, + "<\"POST /api/streams/_disable\", Zod.ZodObject<{}, \"strip\", Zod.ZodTypeAny, {}, {}>, ", + "StreamsRouteHandlerResources", + ", ", + "DisableStreamsResponse", + ", undefined>; \"POST /api/streams/_enable\": ", + { + "pluginId": "@kbn/server-route-repository-utils", + "scope": "common", + "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", + "section": "def-common.ServerRoute", + "text": "ServerRoute" + }, + "<\"POST /api/streams/_enable\", Zod.ZodObject<{}, \"strip\", Zod.ZodTypeAny, {}, {}>, ", + "StreamsRouteHandlerResources", + ", ", + "EnableStreamsResponse", + ", undefined>; \"DELETE /api/streams/{id}\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -699,7 +655,7 @@ "StreamsRouteHandlerResources", ", ", "UpsertStreamResponse", - ", undefined>; \"GET /api/streams/{id}\": ", + ", undefined>; \"GET /api/streams\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -707,9 +663,9 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"GET /api/streams/{id}\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; }, { path: { id: string; }; }>, ", + "<\"GET /api/streams\", Zod.ZodObject<{}, \"strip\", Zod.ZodTypeAny, {}, {}>, ", "StreamsRouteHandlerResources", - ", { name: string; lifecycle: { type: \"dlm\"; data_retention?: string | undefined; } | { type: \"ilm\"; policy: string; }; stream: { ingest: { routing: { name: string; condition?: ", + ", { streams: ({ name: string; stream: { ingest: { routing: { name: string; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -725,7 +681,7 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }[]; wired: { fields: Record; }; }; }; inherited_fields: Record; dashboards?: string[] | undefined; elasticsearch_assets?: { id: string; type: \"ingest_pipeline\" | \"data_stream\" | \"index_template\" | \"component_template\"; }[] | undefined; } | { name: string; lifecycle: { type: \"dlm\"; data_retention?: string | undefined; } | { type: \"ilm\"; policy: string; }; stream: { ingest: { routing: { name: string; condition?: ", + "; }[]; wired: { fields: Record; }; }; }; dashboards?: string[] | undefined; elasticsearch_assets?: { id: string; type: \"ingest_pipeline\" | \"data_stream\" | \"index_template\" | \"component_template\"; }[] | undefined; } | { name: string; stream: { ingest: { routing: { name: string; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -741,7 +697,7 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }[]; }; }; inherited_fields: Record; dashboards?: string[] | undefined; elasticsearch_assets?: { id: string; type: \"ingest_pipeline\" | \"data_stream\" | \"index_template\" | \"component_template\"; }[] | undefined; }, undefined>; \"POST /api/streams/{id}/_fork\": ", + "; }[]; }; }; dashboards?: string[] | undefined; elasticsearch_assets?: { id: string; type: \"ingest_pipeline\" | \"data_stream\" | \"index_template\" | \"component_template\"; }[] | undefined; })[]; }, undefined>; \"GET /api/streams/{id}/_details\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -749,15 +705,21 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"POST /api/streams/{id}/_fork\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; body: Zod.ZodObject<{ stream: Zod.ZodObject<{ name: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { name: string; }, { name: string; }>; condition: Zod.ZodType<", + "<\"GET /api/streams/{id}/_details\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; query: Zod.ZodObject<{ start: Zod.ZodString; end: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { start: string; end: string; }, { start: string; end: string; }>; }, \"strip\", Zod.ZodTypeAny, { query: { start: string; end: string; }; path: { id: string; }; }, { query: { start: string; end: string; }; path: { id: string; }; }>, ", + "StreamsRouteHandlerResources", + ", ", + "StreamDetailsResponse", + ", undefined>; \"GET /api/streams/{id}\": ", { - "pluginId": "@kbn/streams-schema", + "pluginId": "@kbn/server-route-repository-utils", "scope": "common", - "docId": "kibKbnStreamsSchemaPluginApi", - "section": "def-common.Condition", - "text": "Condition" + "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", + "section": "def-common.ServerRoute", + "text": "ServerRoute" }, - ", Zod.ZodTypeDef, ", + "<\"GET /api/streams/{id}\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; }, { path: { id: string; }; }>, ", + "StreamsRouteHandlerResources", + ", { name: string; lifecycle: { type: \"dlm\"; data_retention?: string | undefined; } | { type: \"ilm\"; policy: string; }; stream: { ingest: { routing: { name: string; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -765,7 +727,7 @@ "section": "def-common.Condition", "text": "Condition" }, - ">; }, \"strip\", Zod.ZodTypeAny, { stream: { name: string; }; condition?: ", + "; }[]; processing: { config: { grok: { field: string; patterns: string[]; pattern_definitions?: Record | undefined; ignore_failure?: boolean | undefined; ignore_missing?: boolean | undefined; }; } | { dissect: { field: string; pattern: string; ignore_failure?: boolean | undefined; ignore_missing?: boolean | undefined; append_separator?: string | undefined; }; }; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -773,7 +735,7 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }, { stream: { name: string; }; condition?: ", + "; }[]; wired: { fields: Record; }; }; }; inherited_fields: Record; dashboards?: string[] | undefined; elasticsearch_assets?: { id: string; type: \"ingest_pipeline\" | \"data_stream\" | \"index_template\" | \"component_template\"; }[] | undefined; } | { name: string; lifecycle: { type: \"dlm\"; data_retention?: string | undefined; } | { type: \"ilm\"; policy: string; }; stream: { ingest: { routing: { name: string; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -781,7 +743,7 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; body: { stream: { name: string; }; condition?: ", + "; }[]; processing: { config: { grok: { field: string; patterns: string[]; pattern_definitions?: Record | undefined; ignore_failure?: boolean | undefined; ignore_missing?: boolean | undefined; }; } | { dissect: { field: string; pattern: string; ignore_failure?: boolean | undefined; ignore_missing?: boolean | undefined; append_separator?: string | undefined; }; }; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -789,17 +751,19 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }; }, { path: { id: string; }; body: { stream: { name: string; }; condition?: ", + "; }[]; }; }; inherited_fields: Record; dashboards?: string[] | undefined; elasticsearch_assets?: { id: string; type: \"ingest_pipeline\" | \"data_stream\" | \"index_template\" | \"component_template\"; }[] | undefined; }, undefined>; \"POST /api/streams/{id}/dashboards/_bulk\": ", { - "pluginId": "@kbn/streams-schema", + "pluginId": "@kbn/server-route-repository-utils", "scope": "common", - "docId": "kibKbnStreamsSchemaPluginApi", - "section": "def-common.Condition", - "text": "Condition" + "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", + "section": "def-common.ServerRoute", + "text": "ServerRoute" }, - "; }; }>, ", + "<\"POST /api/streams/{id}/dashboards/_bulk\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; body: Zod.ZodObject<{ operations: Zod.ZodArray; }, \"strip\", Zod.ZodTypeAny, { index: { id: string; }; }, { index: { id: string; }; }>, Zod.ZodObject<{ delete: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; }, \"strip\", Zod.ZodTypeAny, { delete: { id: string; }; }, { delete: { id: string; }; }>]>, \"many\">; }, \"strip\", Zod.ZodTypeAny, { operations: ({ index: { id: string; }; } | { delete: { id: string; }; })[]; }, { operations: ({ index: { id: string; }; } | { delete: { id: string; }; })[]; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; body: { operations: ({ index: { id: string; }; } | { delete: { id: string; }; })[]; }; }, { path: { id: string; }; body: { operations: ({ index: { id: string; }; } | { delete: { id: string; }; })[]; }; }>, ", "StreamsRouteHandlerResources", - ", { acknowledged: true; }, undefined>; \"POST /api/streams/_resync\": ", + ", ", + "BulkUpdateAssetsResponse", + ", undefined>; \"POST /api/streams/{id}/dashboards/_suggestions\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -807,11 +771,11 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"POST /api/streams/_resync\", Zod.ZodObject<{}, \"strip\", Zod.ZodTypeAny, {}, {}>, ", + "<\"POST /api/streams/{id}/dashboards/_suggestions\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; query: Zod.ZodObject<{ query: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { query: string; }, { query: string; }>; body: Zod.ZodObject<{ tags: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { tags?: string[] | undefined; }, { tags?: string[] | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { query: { query: string; }; path: { id: string; }; body: { tags?: string[] | undefined; }; }, { query: { query: string; }; path: { id: string; }; body: { tags?: string[] | undefined; }; }>, ", "StreamsRouteHandlerResources", ", ", - "ResyncStreamsResponse", - ", undefined>; \"POST /api/streams/_enable\": ", + "SuggestDashboardResponse", + ", undefined>; \"DELETE /api/streams/{id}/dashboards/{dashboardId}\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -819,10 +783,46 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"POST /api/streams/_enable\", Zod.ZodObject<{}, \"strip\", Zod.ZodTypeAny, {}, {}>, ", + "<\"DELETE /api/streams/{id}/dashboards/{dashboardId}\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; dashboardId: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; dashboardId: string; }, { id: string; dashboardId: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; dashboardId: string; }; }, { path: { id: string; dashboardId: string; }; }>, ", "StreamsRouteHandlerResources", ", ", - "EnableStreamsResponse", + "UnlinkDashboardResponse", + ", undefined>; \"PUT /api/streams/{id}/dashboards/{dashboardId}\": ", + { + "pluginId": "@kbn/server-route-repository-utils", + "scope": "common", + "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", + "section": "def-common.ServerRoute", + "text": "ServerRoute" + }, + "<\"PUT /api/streams/{id}/dashboards/{dashboardId}\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; dashboardId: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; dashboardId: string; }, { id: string; dashboardId: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; dashboardId: string; }; }, { path: { id: string; dashboardId: string; }; }>, ", + "StreamsRouteHandlerResources", + ", ", + "LinkDashboardResponse", + ", undefined>; \"GET /api/streams/{id}/dashboards\": ", + { + "pluginId": "@kbn/server-route-repository-utils", + "scope": "common", + "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", + "section": "def-common.ServerRoute", + "text": "ServerRoute" + }, + "<\"GET /api/streams/{id}/dashboards\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; }, { path: { id: string; }; }>, ", + "StreamsRouteHandlerResources", + ", ", + "ListDashboardsResponse", + ", undefined>; \"POST /internal/streams/esql\": ", + { + "pluginId": "@kbn/server-route-repository-utils", + "scope": "common", + "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", + "section": "def-common.ServerRoute", + "text": "ServerRoute" + }, + "<\"POST /internal/streams/esql\", Zod.ZodObject<{ body: Zod.ZodObject<{ query: Zod.ZodString; operationName: Zod.ZodString; filter: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">>>; kuery: Zod.ZodOptional; start: Zod.ZodOptional; end: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { query: string; operationName: string; start?: number | undefined; end?: number | undefined; filter?: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\"> | undefined; kuery?: string | undefined; }, { query: string; operationName: string; start?: number | undefined; end?: number | undefined; filter?: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\"> | undefined; kuery?: string | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { body: { query: string; operationName: string; start?: number | undefined; end?: number | undefined; filter?: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\"> | undefined; kuery?: string | undefined; }; }, { body: { query: string; operationName: string; start?: number | undefined; end?: number | undefined; filter?: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\"> | undefined; kuery?: string | undefined; }; }>, ", + "StreamsRouteHandlerResources", + ", ", + "UnparsedEsqlResponse", ", undefined>; }, ", "StreamsRepositoryClientOptions", ">" @@ -880,17 +880,7 @@ "label": "StreamsRouteRepository", "description": [], "signature": [ - "{ \"POST /api/streams/{id}/schema/fields_simulation\": ", - { - "pluginId": "@kbn/server-route-repository-utils", - "scope": "common", - "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", - "section": "def-common.ServerRoute", - "text": "ServerRoute" - }, - "<\"POST /api/streams/{id}/schema/fields_simulation\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; body: Zod.ZodObject<{ field_definitions: Zod.ZodArray; format: Zod.ZodOptional; }, { name: Zod.ZodString; }>, \"strip\", Zod.ZodTypeAny, { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }, { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }>, \"many\">; }, \"strip\", Zod.ZodTypeAny, { field_definitions: { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }[]; }, { field_definitions: { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }[]; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; body: { field_definitions: { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }[]; }; }, { path: { id: string; }; body: { field_definitions: { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }[]; }; }>, ", - "StreamsRouteHandlerResources", - ", { status: \"unknown\" | \"success\" | \"failure\"; simulationError: string | null; documentsWithRuntimeFieldsApplied: unknown[] | null; }, undefined>; \"POST /api/streams/{id}/processing/_simulate\": ", + "{ \"POST /api/streams/{id}/processing/_simulate\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -964,7 +954,7 @@ }, "; }[]; }; }>, ", "StreamsRouteHandlerResources", - ", { documents: { value: Record; isMatch: boolean; }[]; success_rate: number; failure_rate: number; detected_fields: { name: string; type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\" | \"unmapped\"; }[]; }, undefined>; \"GET /api/streams/{id}/schema/unmapped_fields\": ", + ", { documents: { value: Record; isMatch: boolean; }[]; success_rate: number; failure_rate: number; detected_fields: { name: string; type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\" | \"unmapped\"; }[]; }, undefined>; \"POST /api/streams/{id}/schema/fields_simulation\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -972,9 +962,9 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"GET /api/streams/{id}/schema/unmapped_fields\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; }, { path: { id: string; }; }>, ", + "<\"POST /api/streams/{id}/schema/fields_simulation\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; body: Zod.ZodObject<{ field_definitions: Zod.ZodArray; format: Zod.ZodOptional; }, { name: Zod.ZodString; }>, \"strip\", Zod.ZodTypeAny, { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }, { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }>, \"many\">; }, \"strip\", Zod.ZodTypeAny, { field_definitions: { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }[]; }, { field_definitions: { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }[]; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; body: { field_definitions: { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }[]; }; }, { path: { id: string; }; body: { field_definitions: { type: \"boolean\" | \"ip\" | \"keyword\" | \"date\" | \"long\" | \"double\" | \"match_only_text\"; name: string; format?: string | undefined; }[]; }; }>, ", "StreamsRouteHandlerResources", - ", { unmappedFields: string[]; }, undefined>; \"GET /api/streams/{id}/_details\": ", + ", { status: \"unknown\" | \"success\" | \"failure\"; simulationError: string | null; documentsWithRuntimeFieldsApplied: unknown[] | null; }, undefined>; \"GET /api/streams/{id}/schema/unmapped_fields\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -982,11 +972,9 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"GET /api/streams/{id}/_details\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; query: Zod.ZodObject<{ start: Zod.ZodString; end: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { start: string; end: string; }, { start: string; end: string; }>; }, \"strip\", Zod.ZodTypeAny, { query: { start: string; end: string; }; path: { id: string; }; }, { query: { start: string; end: string; }; path: { id: string; }; }>, ", + "<\"GET /api/streams/{id}/schema/unmapped_fields\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; }, { path: { id: string; }; }>, ", "StreamsRouteHandlerResources", - ", ", - "StreamDetailsResponse", - ", undefined>; \"POST /api/streams/{id}/_sample\": ", + ", { unmappedFields: string[]; }, undefined>; \"POST /api/streams/{id}/_sample\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -1044,55 +1032,11 @@ }, "; }; }>, ", "StreamsRouteHandlerResources", - ", { documents: unknown[]; }, undefined>; \"POST /api/streams/{id}/dashboards/_bulk\": ", - { - "pluginId": "@kbn/server-route-repository-utils", - "scope": "common", - "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", - "section": "def-common.ServerRoute", - "text": "ServerRoute" - }, - "<\"POST /api/streams/{id}/dashboards/_bulk\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; body: Zod.ZodObject<{ operations: Zod.ZodArray; }, \"strip\", Zod.ZodTypeAny, { index: { id: string; }; }, { index: { id: string; }; }>, Zod.ZodObject<{ delete: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; }, \"strip\", Zod.ZodTypeAny, { delete: { id: string; }; }, { delete: { id: string; }; }>]>, \"many\">; }, \"strip\", Zod.ZodTypeAny, { operations: ({ index: { id: string; }; } | { delete: { id: string; }; })[]; }, { operations: ({ index: { id: string; }; } | { delete: { id: string; }; })[]; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; body: { operations: ({ index: { id: string; }; } | { delete: { id: string; }; })[]; }; }, { path: { id: string; }; body: { operations: ({ index: { id: string; }; } | { delete: { id: string; }; })[]; }; }>, ", - "StreamsRouteHandlerResources", - ", ", - "BulkUpdateAssetsResponse", - ", undefined>; \"POST /api/streams/{id}/dashboards/_suggestions\": ", - { - "pluginId": "@kbn/server-route-repository-utils", - "scope": "common", - "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", - "section": "def-common.ServerRoute", - "text": "ServerRoute" - }, - "<\"POST /api/streams/{id}/dashboards/_suggestions\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; query: Zod.ZodObject<{ query: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { query: string; }, { query: string; }>; body: Zod.ZodObject<{ tags: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { tags?: string[] | undefined; }, { tags?: string[] | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { query: { query: string; }; path: { id: string; }; body: { tags?: string[] | undefined; }; }, { query: { query: string; }; path: { id: string; }; body: { tags?: string[] | undefined; }; }>, ", - "StreamsRouteHandlerResources", - ", ", - "SuggestDashboardResponse", - ", undefined>; \"DELETE /api/streams/{id}/dashboards/{dashboardId}\": ", - { - "pluginId": "@kbn/server-route-repository-utils", - "scope": "common", - "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", - "section": "def-common.ServerRoute", - "text": "ServerRoute" - }, - "<\"DELETE /api/streams/{id}/dashboards/{dashboardId}\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; dashboardId: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; dashboardId: string; }, { id: string; dashboardId: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; dashboardId: string; }; }, { path: { id: string; dashboardId: string; }; }>, ", - "StreamsRouteHandlerResources", - ", ", - "UnlinkDashboardResponse", - ", undefined>; \"PUT /api/streams/{id}/dashboards/{dashboardId}\": ", - { - "pluginId": "@kbn/server-route-repository-utils", - "scope": "common", - "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", - "section": "def-common.ServerRoute", - "text": "ServerRoute" - }, - "<\"PUT /api/streams/{id}/dashboards/{dashboardId}\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; dashboardId: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; dashboardId: string; }, { id: string; dashboardId: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; dashboardId: string; }; }, { path: { id: string; dashboardId: string; }; }>, ", + ", { documents: unknown[]; }, undefined>; \"GET /api/streams/_status\": { endpoint: \"GET /api/streams/_status\"; handler: ServerRouteHandler<", "StreamsRouteHandlerResources", - ", ", - "LinkDashboardResponse", - ", undefined>; \"GET /api/streams/{id}/dashboards\": ", + ", undefined, { enabled: boolean; }>; security?: ", + "RouteSecurity", + " | undefined; }; \"POST /api/streams/_resync\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -1100,11 +1044,11 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"GET /api/streams/{id}/dashboards\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; }, { path: { id: string; }; }>, ", + "<\"POST /api/streams/_resync\", Zod.ZodObject<{}, \"strip\", Zod.ZodTypeAny, {}, {}>, ", "StreamsRouteHandlerResources", ", ", - "ListDashboardsResponse", - ", undefined>; \"POST /api/streams/_disable\": ", + "ResyncStreamsResponse", + ", undefined>; \"POST /api/streams/{id}/_fork\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -1112,37 +1056,23 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"POST /api/streams/_disable\", Zod.ZodObject<{}, \"strip\", Zod.ZodTypeAny, {}, {}>, ", - "StreamsRouteHandlerResources", - ", ", - "DisableStreamsResponse", - ", undefined>; \"POST /internal/streams/esql\": ", + "<\"POST /api/streams/{id}/_fork\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; body: Zod.ZodObject<{ stream: Zod.ZodObject<{ name: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { name: string; }, { name: string; }>; condition: Zod.ZodType<", { - "pluginId": "@kbn/server-route-repository-utils", + "pluginId": "@kbn/streams-schema", "scope": "common", - "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", - "section": "def-common.ServerRoute", - "text": "ServerRoute" + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.Condition", + "text": "Condition" }, - "<\"POST /internal/streams/esql\", Zod.ZodObject<{ body: Zod.ZodObject<{ query: Zod.ZodString; operationName: Zod.ZodString; filter: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">>>; kuery: Zod.ZodOptional; start: Zod.ZodOptional; end: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { query: string; operationName: string; start?: number | undefined; end?: number | undefined; filter?: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\"> | undefined; kuery?: string | undefined; }, { query: string; operationName: string; start?: number | undefined; end?: number | undefined; filter?: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\"> | undefined; kuery?: string | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { body: { query: string; operationName: string; start?: number | undefined; end?: number | undefined; filter?: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\"> | undefined; kuery?: string | undefined; }; }, { body: { query: string; operationName: string; start?: number | undefined; end?: number | undefined; filter?: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\"> | undefined; kuery?: string | undefined; }; }>, ", - "StreamsRouteHandlerResources", - ", ", - "UnparsedEsqlResponse", - ", undefined>; \"GET /api/streams/_status\": { endpoint: \"GET /api/streams/_status\"; handler: ServerRouteHandler<", - "StreamsRouteHandlerResources", - ", undefined, { enabled: boolean; }>; security?: ", - "RouteSecurity", - " | undefined; }; \"GET /api/streams\": ", + ", Zod.ZodTypeDef, ", { - "pluginId": "@kbn/server-route-repository-utils", + "pluginId": "@kbn/streams-schema", "scope": "common", - "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", - "section": "def-common.ServerRoute", - "text": "ServerRoute" + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.Condition", + "text": "Condition" }, - "<\"GET /api/streams\", Zod.ZodObject<{}, \"strip\", Zod.ZodTypeAny, {}, {}>, ", - "StreamsRouteHandlerResources", - ", { streams: ({ name: string; stream: { ingest: { routing: { name: string; condition?: ", + ">; }, \"strip\", Zod.ZodTypeAny, { stream: { name: string; }; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -1150,7 +1080,7 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }[]; processing: { config: { grok: { field: string; patterns: string[]; pattern_definitions?: Record | undefined; ignore_failure?: boolean | undefined; ignore_missing?: boolean | undefined; }; } | { dissect: { field: string; pattern: string; ignore_failure?: boolean | undefined; ignore_missing?: boolean | undefined; append_separator?: string | undefined; }; }; condition?: ", + "; }, { stream: { name: string; }; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -1158,7 +1088,7 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }[]; wired: { fields: Record; }; }; }; dashboards?: string[] | undefined; elasticsearch_assets?: { id: string; type: \"ingest_pipeline\" | \"data_stream\" | \"index_template\" | \"component_template\"; }[] | undefined; } | { name: string; stream: { ingest: { routing: { name: string; condition?: ", + "; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; body: { stream: { name: string; }; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -1166,7 +1096,7 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }[]; processing: { config: { grok: { field: string; patterns: string[]; pattern_definitions?: Record | undefined; ignore_failure?: boolean | undefined; ignore_missing?: boolean | undefined; }; } | { dissect: { field: string; pattern: string; ignore_failure?: boolean | undefined; ignore_missing?: boolean | undefined; append_separator?: string | undefined; }; }; condition?: ", + "; }; }, { path: { id: string; }; body: { stream: { name: string; }; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -1174,7 +1104,33 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }[]; }; }; dashboards?: string[] | undefined; elasticsearch_assets?: { id: string; type: \"ingest_pipeline\" | \"data_stream\" | \"index_template\" | \"component_template\"; }[] | undefined; })[]; }, undefined>; \"DELETE /api/streams/{id}\": ", + "; }; }>, ", + "StreamsRouteHandlerResources", + ", { acknowledged: true; }, undefined>; \"POST /api/streams/_disable\": ", + { + "pluginId": "@kbn/server-route-repository-utils", + "scope": "common", + "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", + "section": "def-common.ServerRoute", + "text": "ServerRoute" + }, + "<\"POST /api/streams/_disable\", Zod.ZodObject<{}, \"strip\", Zod.ZodTypeAny, {}, {}>, ", + "StreamsRouteHandlerResources", + ", ", + "DisableStreamsResponse", + ", undefined>; \"POST /api/streams/_enable\": ", + { + "pluginId": "@kbn/server-route-repository-utils", + "scope": "common", + "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", + "section": "def-common.ServerRoute", + "text": "ServerRoute" + }, + "<\"POST /api/streams/_enable\", Zod.ZodObject<{}, \"strip\", Zod.ZodTypeAny, {}, {}>, ", + "StreamsRouteHandlerResources", + ", ", + "EnableStreamsResponse", + ", undefined>; \"DELETE /api/streams/{id}\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -1516,7 +1472,7 @@ "StreamsRouteHandlerResources", ", ", "UpsertStreamResponse", - ", undefined>; \"GET /api/streams/{id}\": ", + ", undefined>; \"GET /api/streams\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -1524,9 +1480,9 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"GET /api/streams/{id}\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; }, { path: { id: string; }; }>, ", + "<\"GET /api/streams\", Zod.ZodObject<{}, \"strip\", Zod.ZodTypeAny, {}, {}>, ", "StreamsRouteHandlerResources", - ", { name: string; lifecycle: { type: \"dlm\"; data_retention?: string | undefined; } | { type: \"ilm\"; policy: string; }; stream: { ingest: { routing: { name: string; condition?: ", + ", { streams: ({ name: string; stream: { ingest: { routing: { name: string; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -1542,7 +1498,7 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }[]; wired: { fields: Record; }; }; }; inherited_fields: Record; dashboards?: string[] | undefined; elasticsearch_assets?: { id: string; type: \"ingest_pipeline\" | \"data_stream\" | \"index_template\" | \"component_template\"; }[] | undefined; } | { name: string; lifecycle: { type: \"dlm\"; data_retention?: string | undefined; } | { type: \"ilm\"; policy: string; }; stream: { ingest: { routing: { name: string; condition?: ", + "; }[]; wired: { fields: Record; }; }; }; dashboards?: string[] | undefined; elasticsearch_assets?: { id: string; type: \"ingest_pipeline\" | \"data_stream\" | \"index_template\" | \"component_template\"; }[] | undefined; } | { name: string; stream: { ingest: { routing: { name: string; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -1558,7 +1514,7 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }[]; }; }; inherited_fields: Record; dashboards?: string[] | undefined; elasticsearch_assets?: { id: string; type: \"ingest_pipeline\" | \"data_stream\" | \"index_template\" | \"component_template\"; }[] | undefined; }, undefined>; \"POST /api/streams/{id}/_fork\": ", + "; }[]; }; }; dashboards?: string[] | undefined; elasticsearch_assets?: { id: string; type: \"ingest_pipeline\" | \"data_stream\" | \"index_template\" | \"component_template\"; }[] | undefined; })[]; }, undefined>; \"GET /api/streams/{id}/_details\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -1566,15 +1522,21 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"POST /api/streams/{id}/_fork\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; body: Zod.ZodObject<{ stream: Zod.ZodObject<{ name: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { name: string; }, { name: string; }>; condition: Zod.ZodType<", + "<\"GET /api/streams/{id}/_details\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; query: Zod.ZodObject<{ start: Zod.ZodString; end: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { start: string; end: string; }, { start: string; end: string; }>; }, \"strip\", Zod.ZodTypeAny, { query: { start: string; end: string; }; path: { id: string; }; }, { query: { start: string; end: string; }; path: { id: string; }; }>, ", + "StreamsRouteHandlerResources", + ", ", + "StreamDetailsResponse", + ", undefined>; \"GET /api/streams/{id}\": ", { - "pluginId": "@kbn/streams-schema", + "pluginId": "@kbn/server-route-repository-utils", "scope": "common", - "docId": "kibKbnStreamsSchemaPluginApi", - "section": "def-common.Condition", - "text": "Condition" + "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", + "section": "def-common.ServerRoute", + "text": "ServerRoute" }, - ", Zod.ZodTypeDef, ", + "<\"GET /api/streams/{id}\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; }, { path: { id: string; }; }>, ", + "StreamsRouteHandlerResources", + ", { name: string; lifecycle: { type: \"dlm\"; data_retention?: string | undefined; } | { type: \"ilm\"; policy: string; }; stream: { ingest: { routing: { name: string; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -1582,7 +1544,7 @@ "section": "def-common.Condition", "text": "Condition" }, - ">; }, \"strip\", Zod.ZodTypeAny, { stream: { name: string; }; condition?: ", + "; }[]; processing: { config: { grok: { field: string; patterns: string[]; pattern_definitions?: Record | undefined; ignore_failure?: boolean | undefined; ignore_missing?: boolean | undefined; }; } | { dissect: { field: string; pattern: string; ignore_failure?: boolean | undefined; ignore_missing?: boolean | undefined; append_separator?: string | undefined; }; }; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -1590,7 +1552,7 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }, { stream: { name: string; }; condition?: ", + "; }[]; wired: { fields: Record; }; }; }; inherited_fields: Record; dashboards?: string[] | undefined; elasticsearch_assets?: { id: string; type: \"ingest_pipeline\" | \"data_stream\" | \"index_template\" | \"component_template\"; }[] | undefined; } | { name: string; lifecycle: { type: \"dlm\"; data_retention?: string | undefined; } | { type: \"ilm\"; policy: string; }; stream: { ingest: { routing: { name: string; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -1598,7 +1560,7 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; body: { stream: { name: string; }; condition?: ", + "; }[]; processing: { config: { grok: { field: string; patterns: string[]; pattern_definitions?: Record | undefined; ignore_failure?: boolean | undefined; ignore_missing?: boolean | undefined; }; } | { dissect: { field: string; pattern: string; ignore_failure?: boolean | undefined; ignore_missing?: boolean | undefined; append_separator?: string | undefined; }; }; condition?: ", { "pluginId": "@kbn/streams-schema", "scope": "common", @@ -1606,17 +1568,19 @@ "section": "def-common.Condition", "text": "Condition" }, - "; }; }, { path: { id: string; }; body: { stream: { name: string; }; condition?: ", + "; }[]; }; }; inherited_fields: Record; dashboards?: string[] | undefined; elasticsearch_assets?: { id: string; type: \"ingest_pipeline\" | \"data_stream\" | \"index_template\" | \"component_template\"; }[] | undefined; }, undefined>; \"POST /api/streams/{id}/dashboards/_bulk\": ", { - "pluginId": "@kbn/streams-schema", + "pluginId": "@kbn/server-route-repository-utils", "scope": "common", - "docId": "kibKbnStreamsSchemaPluginApi", - "section": "def-common.Condition", - "text": "Condition" + "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", + "section": "def-common.ServerRoute", + "text": "ServerRoute" }, - "; }; }>, ", + "<\"POST /api/streams/{id}/dashboards/_bulk\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; body: Zod.ZodObject<{ operations: Zod.ZodArray; }, \"strip\", Zod.ZodTypeAny, { index: { id: string; }; }, { index: { id: string; }; }>, Zod.ZodObject<{ delete: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; }, \"strip\", Zod.ZodTypeAny, { delete: { id: string; }; }, { delete: { id: string; }; }>]>, \"many\">; }, \"strip\", Zod.ZodTypeAny, { operations: ({ index: { id: string; }; } | { delete: { id: string; }; })[]; }, { operations: ({ index: { id: string; }; } | { delete: { id: string; }; })[]; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; body: { operations: ({ index: { id: string; }; } | { delete: { id: string; }; })[]; }; }, { path: { id: string; }; body: { operations: ({ index: { id: string; }; } | { delete: { id: string; }; })[]; }; }>, ", "StreamsRouteHandlerResources", - ", { acknowledged: true; }, undefined>; \"POST /api/streams/_resync\": ", + ", ", + "BulkUpdateAssetsResponse", + ", undefined>; \"POST /api/streams/{id}/dashboards/_suggestions\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -1624,11 +1588,11 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"POST /api/streams/_resync\", Zod.ZodObject<{}, \"strip\", Zod.ZodTypeAny, {}, {}>, ", + "<\"POST /api/streams/{id}/dashboards/_suggestions\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; query: Zod.ZodObject<{ query: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { query: string; }, { query: string; }>; body: Zod.ZodObject<{ tags: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { tags?: string[] | undefined; }, { tags?: string[] | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { query: { query: string; }; path: { id: string; }; body: { tags?: string[] | undefined; }; }, { query: { query: string; }; path: { id: string; }; body: { tags?: string[] | undefined; }; }>, ", "StreamsRouteHandlerResources", ", ", - "ResyncStreamsResponse", - ", undefined>; \"POST /api/streams/_enable\": ", + "SuggestDashboardResponse", + ", undefined>; \"DELETE /api/streams/{id}/dashboards/{dashboardId}\": ", { "pluginId": "@kbn/server-route-repository-utils", "scope": "common", @@ -1636,10 +1600,46 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"POST /api/streams/_enable\", Zod.ZodObject<{}, \"strip\", Zod.ZodTypeAny, {}, {}>, ", + "<\"DELETE /api/streams/{id}/dashboards/{dashboardId}\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; dashboardId: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; dashboardId: string; }, { id: string; dashboardId: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; dashboardId: string; }; }, { path: { id: string; dashboardId: string; }; }>, ", "StreamsRouteHandlerResources", ", ", - "EnableStreamsResponse", + "UnlinkDashboardResponse", + ", undefined>; \"PUT /api/streams/{id}/dashboards/{dashboardId}\": ", + { + "pluginId": "@kbn/server-route-repository-utils", + "scope": "common", + "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", + "section": "def-common.ServerRoute", + "text": "ServerRoute" + }, + "<\"PUT /api/streams/{id}/dashboards/{dashboardId}\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; dashboardId: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; dashboardId: string; }, { id: string; dashboardId: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; dashboardId: string; }; }, { path: { id: string; dashboardId: string; }; }>, ", + "StreamsRouteHandlerResources", + ", ", + "LinkDashboardResponse", + ", undefined>; \"GET /api/streams/{id}/dashboards\": ", + { + "pluginId": "@kbn/server-route-repository-utils", + "scope": "common", + "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", + "section": "def-common.ServerRoute", + "text": "ServerRoute" + }, + "<\"GET /api/streams/{id}/dashboards\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; }, { path: { id: string; }; }>, ", + "StreamsRouteHandlerResources", + ", ", + "ListDashboardsResponse", + ", undefined>; \"POST /internal/streams/esql\": ", + { + "pluginId": "@kbn/server-route-repository-utils", + "scope": "common", + "docId": "kibKbnServerRouteRepositoryUtilsPluginApi", + "section": "def-common.ServerRoute", + "text": "ServerRoute" + }, + "<\"POST /internal/streams/esql\", Zod.ZodObject<{ body: Zod.ZodObject<{ query: Zod.ZodString; operationName: Zod.ZodString; filter: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">>>; kuery: Zod.ZodOptional; start: Zod.ZodOptional; end: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { query: string; operationName: string; start?: number | undefined; end?: number | undefined; filter?: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\"> | undefined; kuery?: string | undefined; }, { query: string; operationName: string; start?: number | undefined; end?: number | undefined; filter?: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\"> | undefined; kuery?: string | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { body: { query: string; operationName: string; start?: number | undefined; end?: number | undefined; filter?: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\"> | undefined; kuery?: string | undefined; }; }, { body: { query: string; operationName: string; start?: number | undefined; end?: number | undefined; filter?: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\"> | undefined; kuery?: string | undefined; }; }>, ", + "StreamsRouteHandlerResources", + ", ", + "UnparsedEsqlResponse", ", undefined>; }" ], "path": "x-pack/solutions/observability/plugins/streams/server/routes/index.ts", diff --git a/api_docs/streams.mdx b/api_docs/streams.mdx index 413aefd27d9f1..b776051e960d9 100644 --- a/api_docs/streams.mdx +++ b/api_docs/streams.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/streams title: "streams" image: https://source.unsplash.com/400x175/?github description: API docs for the streams plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'streams'] --- import streamsObj from './streams.devdocs.json'; diff --git a/api_docs/streams_app.mdx b/api_docs/streams_app.mdx index e147ed26400a9..dea90e36a74a6 100644 --- a/api_docs/streams_app.mdx +++ b/api_docs/streams_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/streamsApp title: "streamsApp" image: https://source.unsplash.com/400x175/?github description: API docs for the streamsApp plugin -date: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'streamsApp'] --- import streamsAppObj from './streams_app.devdocs.json'; diff --git a/api_docs/task_manager.devdocs.json b/api_docs/task_manager.devdocs.json index 6c8d2270f1d50..e51e55bf783b0 100644 --- a/api_docs/task_manager.devdocs.json +++ b/api_docs/task_manager.devdocs.json @@ -1286,6 +1286,27 @@ "path": "x-pack/platform/plugins/shared/task_manager/server/task.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "taskManager", + "id": "def-server.TaskInstance.priority", + "type": "CompoundType", + "tags": [], + "label": "priority", + "description": [], + "signature": [ + { + "pluginId": "taskManager", + "scope": "server", + "docId": "kibTaskManagerPluginApi", + "section": "def-server.TaskPriority", + "text": "TaskPriority" + }, + " | undefined" + ], + "path": "x-pack/platform/plugins/shared/task_manager/server/task.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index b337d8f080f1d..126cf561acfc1 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.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 | |-------------------|-----------|------------------------|-----------------| -| 104 | 0 | 61 | 7 | +| 105 | 0 | 62 | 7 | ## Server diff --git a/api_docs/telemetry.devdocs.json b/api_docs/telemetry.devdocs.json index 5b05765b189d0..9746d7b5d5a2b 100644 --- a/api_docs/telemetry.devdocs.json +++ b/api_docs/telemetry.devdocs.json @@ -201,6 +201,19 @@ "path": "src/platform/plugins/shared/telemetry/public/plugin.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "telemetry", + "id": "def-public.TelemetryPluginConfig.localShipper", + "type": "boolean", + "tags": [], + "label": "localShipper", + "description": [ + "Should use the local EBT shipper to persist events in the local ES" + ], + "path": "src/platform/plugins/shared/telemetry/public/plugin.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -790,7 +803,7 @@ "id": "def-server.TelemetryPluginStart.getIsOptedIn", "type": "Function", "tags": [ - "track-adoption" + "deprecated" ], "label": "getIsOptedIn", "description": [ @@ -800,8 +813,8 @@ "() => Promise" ], "path": "src/platform/plugins/shared/telemetry/server/plugin.ts", - "deprecated": false, - "trackAdoption": true, + "deprecated": true, + "trackAdoption": false, "references": [ { "plugin": "fleet", @@ -846,6 +859,47 @@ ], "children": [], "returnComment": [] + }, + { + "parentPluginId": "telemetry", + "id": "def-server.TelemetryPluginStart.isOptedIn$", + "type": "Object", + "tags": [ + "track-adoption" + ], + "label": "isOptedIn$", + "description": [ + "\nAn Observable object that can be subscribed to for changes in global telemetry config.\n\nPushes `true` when sending usage to Elastic is enabled.\nPushes `false` when the user explicitly opts out of sending usage data to Elastic.\n\nAdditionally, pushes the actual value on Kibana startup, except if the (previously opted-out) user\nhaven't chosen yet to opt-in or out after a minor or major upgrade. In that case, pushing the new\nvalue waits until the user decides.\n" + ], + "signature": [ + "Observable", + "" + ], + "path": "src/platform/plugins/shared/telemetry/server/plugin.ts", + "deprecated": false, + "trackAdoption": true, + "references": [ + { + "plugin": "fleet", + "path": "x-pack/platform/plugins/shared/fleet/server/telemetry/sender.test.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/platform/plugins/shared/fleet/server/telemetry/sender.test.ts" + }, + { + "plugin": "synthetics", + "path": "x-pack/solutions/observability/plugins/synthetics/server/telemetry/sender.test.ts" + }, + { + "plugin": "synthetics", + "path": "x-pack/solutions/observability/plugins/synthetics/server/telemetry/sender.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/solutions/security/plugins/security_solution/server/lib/telemetry/sender.test.ts" + } + ] } ], "lifecycle": "start", diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index f4507898e29a2..de3716ed20043 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 45 | 0 | 1 | 0 | +| 47 | 0 | 1 | 0 | ## Client diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index cd300bc208a06..35bb3ed7ceaa5 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index ceea2d6895219..0a6500ad1b9b9 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/threat_intelligence.devdocs.json b/api_docs/threat_intelligence.devdocs.json index f55a8d2199db8..c0f838576eef5 100644 --- a/api_docs/threat_intelligence.devdocs.json +++ b/api_docs/threat_intelligence.devdocs.json @@ -180,6 +180,19 @@ ], "returnComment": [] }, + { + "parentPluginId": "threatIntelligence", + "id": "def-public.SecuritySolutionPluginContext.hasAccessToTimeline", + "type": "boolean", + "tags": [], + "label": "hasAccessToTimeline", + "description": [ + "\nWhether the current user has access to timeline" + ], + "path": "x-pack/solutions/security/plugins/threat_intelligence/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "threatIntelligence", "id": "def-public.SecuritySolutionPluginContext.useQuery", diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index 47b2faf06f50f..7c9d314b92583 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-threat-hunting-investigations](https://github.com/org | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 30 | 0 | 14 | 4 | +| 31 | 0 | 14 | 4 | ## Client diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index cba1d05caa3bb..5c86f102c5740 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: 2025-01-16 +date: 2025-01-21 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 48fb26f7ed0f3..935156f826515 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: 2025-01-16 +date: 2025-01-21 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 f08c7acca111a..32b7569a851e9 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.devdocs.json b/api_docs/ui_actions.devdocs.json index c6fb3dcdd966f..a56bdc273bb5d 100644 --- a/api_docs/ui_actions.devdocs.json +++ b/api_docs/ui_actions.devdocs.json @@ -318,18 +318,6 @@ "plugin": "uiActionsEnhanced", "path": "src/platform/plugins/shared/ui_actions_enhanced/public/dynamic_actions/dynamic_action_manager.ts" }, - { - "plugin": "controls", - "path": "src/platform/plugins/shared/controls/public/plugin.ts" - }, - { - "plugin": "controls", - "path": "src/platform/plugins/shared/controls/public/plugin.ts" - }, - { - "plugin": "controls", - "path": "src/platform/plugins/shared/controls/public/plugin.ts" - }, { "plugin": "ml", "path": "x-pack/platform/plugins/shared/ml/public/ui_actions/index.ts" diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index a540a05f997b7..e526418928a8a 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: 2025-01-16 +date: 2025-01-21 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 f202d6d9835fb..85a54f015d81f 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: 2025-01-16 +date: 2025-01-21 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 7d8c75daaf0a8..a1d20100c23dd 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedDocViewer'] --- import unifiedDocViewerObj from './unified_doc_viewer.devdocs.json'; diff --git a/api_docs/unified_histogram.devdocs.json b/api_docs/unified_histogram.devdocs.json index 9410d95fada92..0c6bc9b169c12 100644 --- a/api_docs/unified_histogram.devdocs.json +++ b/api_docs/unified_histogram.devdocs.json @@ -1880,7 +1880,7 @@ "\nThe API exposed by the container" ], "signature": [ - "{ refetch: () => void; } & Pick<", + "{ fetch: () => void; } & Pick<", "UnifiedHistogramStateService", ", \"state$\" | \"setChartHidden\" | \"setTopPanelHeight\" | \"setTimeInterval\" | \"setTotalHits\">" ], diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index f9bf9aa99ebda..919d73333631b 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: 2025-01-16 +date: 2025-01-21 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 857c3061b6f8e..085a8ca841263 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: 2025-01-16 +date: 2025-01-21 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 1da8ad1513586..44af0ac1dc7d6 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: 2025-01-16 +date: 2025-01-21 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 49b071f4e6e9d..bf80bdb22d021 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: 2025-01-16 +date: 2025-01-21 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 55a4b3d8007a0..53235bc39c855 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: 2025-01-16 +date: 2025-01-21 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 b416815f2950e..d717fb9a6fb84 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: 2025-01-16 +date: 2025-01-21 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 25cc74843b4b2..bd8048b5dba75 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: 2025-01-16 +date: 2025-01-21 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 07342a9251bb0..1ad6b0e65d189 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: 2025-01-16 +date: 2025-01-21 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 78ef1e8b36c91..6261af129f1f1 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: 2025-01-16 +date: 2025-01-21 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 a267cc7529ef4..5a816d94d632d 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: 2025-01-16 +date: 2025-01-21 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 5766fdf0aead4..2875844f90973 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: 2025-01-16 +date: 2025-01-21 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 bfec3f10460fa..1c3c4799009c6 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: 2025-01-16 +date: 2025-01-21 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 cb90adef1c0e4..2f7acce8fc781 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: 2025-01-16 +date: 2025-01-21 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 396fa685701f9..c5a4432b80944 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: 2025-01-16 +date: 2025-01-21 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 7bb2a1a5904e0..54cfcd29f73ee 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: 2025-01-16 +date: 2025-01-21 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 ba158dac471e2..0f87e2324caa9 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: 2025-01-16 +date: 2025-01-21 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 3c5500949e8ee..e9681323b4d30 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: 2025-01-16 +date: 2025-01-21 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 46f89f59355e4..48f8f9b075849 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: 2025-01-16 +date: 2025-01-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; diff --git a/config/serverless.security.yml b/config/serverless.security.yml index f748c3ea5b7b2..ab0157c0183fa 100644 --- a/config/serverless.security.yml +++ b/config/serverless.security.yml @@ -24,6 +24,33 @@ xpack.features.overrides: category: "security" order: 1101 ### Security's feature privileges are fine-tuned to grant access to Discover, Dashboard, Maps, and Visualize apps. + siemV2: + privileges: + ### Security's `All` feature privilege should implicitly grant `All` access to Discover, Dashboard, Maps, and + ### Visualize features. + all.composedOf: + - feature: "discover" + privileges: [ "all" ] + - feature: "dashboard" + privileges: [ "all" ] + - feature: "visualize" + privileges: [ "all" ] + - feature: "maps" + privileges: [ "all" ] + # Security's `Read` feature privilege should implicitly grant `Read` access to Discover, Dashboard, Maps, and + # Visualize features. Additionally, it should implicitly grant privilege to create short URLs in Discover, + ### Dashboard, and Visualize apps. + read.composedOf: + - feature: "discover" + privileges: [ "read" ] + - feature: "dashboard" + privileges: [ "read" ] + - feature: "visualize" + privileges: [ "read" ] + - feature: "maps" + privileges: [ "read" ] + + ### Security's feature privileges are fine-tuned to grant access to Discover, Dashboard, Maps, and Visualize apps. siem: privileges: ### Security's `All` feature privilege should implicitly grant `All` access to Discover, Dashboard, Maps, and diff --git a/config/serverless.yml b/config/serverless.yml index e7629c5053fa4..cbaf654db3867 100644 --- a/config/serverless.yml +++ b/config/serverless.yml @@ -234,3 +234,6 @@ discover.enableUiSettingsValidations: true xpack.dataUsage.enabled: true # This feature is disabled in Serverless until fully tested within a Serverless environment xpack.dataUsage.enableExperimental: ['dataUsageDisabled'] + +# Ensure Serverless is using the Amsterdam theme +uiSettings.experimental.defaultTheme: "amsterdam" diff --git a/dev_docs/nav-kibana-dev.docnav.json b/dev_docs/nav-kibana-dev.docnav.json index 976bab0d8316f..cdfb8fab07fcd 100644 --- a/dev_docs/nav-kibana-dev.docnav.json +++ b/dev_docs/nav-kibana-dev.docnav.json @@ -197,6 +197,9 @@ { "id": "kibDevTutorialDebugging" }, + { + "id": "kibDevTutorialDebuggingFipsTestFailures" + }, { "id": "kibDevTutorialBuildingDistributable", "label": "Building a Kibana distributable" diff --git a/docs/management/connectors/action-types/crowdstrike.asciidoc b/docs/management/connectors/action-types/crowdstrike.asciidoc index 813b6a699a71c..5e9c38a528765 100644 --- a/docs/management/connectors/action-types/crowdstrike.asciidoc +++ b/docs/management/connectors/action-types/crowdstrike.asciidoc @@ -12,6 +12,8 @@ preview::[] The CrowdStrike connector communicates with CrowdStrike Management Console via REST API. +To use this connector, you must have authority to run {endpoint-sec} connectors, which is an *{connectors-feature}* sub-feature privilege. Refer to <>. + [float] [[define-crowdstrike-ui]] === Create connectors in {kib} diff --git a/docs/management/connectors/action-types/sentinelone.asciidoc b/docs/management/connectors/action-types/sentinelone.asciidoc index 4fbc16ba5aafa..71dc4a3462ee2 100644 --- a/docs/management/connectors/action-types/sentinelone.asciidoc +++ b/docs/management/connectors/action-types/sentinelone.asciidoc @@ -12,6 +12,8 @@ preview::[] The SentinelOne connector communicates with SentinelOne Management Console via REST API. +To use this connector, you must have authority to run {endpoint-sec} connectors, which is an *{connectors-feature}* sub-feature privilege. Refer to <>. + [float] [[define-sentinelone-ui]] === Create connectors in {kib} diff --git a/docs/upgrade-notes.asciidoc b/docs/upgrade-notes.asciidoc index 31ae28821e907..17ab878508341 100644 --- a/docs/upgrade-notes.asciidoc +++ b/docs/upgrade-notes.asciidoc @@ -48,6 +48,33 @@ For Elastic Security solution release information, refer to {security-guide}/rel [float] === Breaking changes +[discrete] +[[breaking-199598]] +.Remove deprecated endpoint management endpoints (9.0.0) +[%collapsible] +==== +*Details* + +-- +* `POST /api/endpoint/isolate` has been replaced by `POST /api/endpoint/action/isolate` +* `POST /api/endpoint/unisolate` has been replaced by `POST /api/endpoint/action/unisolate` +* `GET /api/endpoint/policy/summaries` has been deprecated without replacement. Will be removed in v9.0.0 +* `POST /api/endpoint/suggestions/{suggestion_type}` has been deprecated without replacement. Will be removed in v9.0.0 +* `GET /api/endpoint/action_log/{agent_id}` has been deprecated without replacement. Will be removed in v9.0.0 +* `GET /api/endpoint/metadata/transforms` has been deprecated without replacement. Will be removed in v9.0.0 +-- + +*Impact* + +Deprecated endpoints will fail with a 404 status code starting from version 9.0.0 + +*Action* + +-- +* Remove references to `GET /api/endpoint/policy/summaries` endpoint. +* Remove references to `POST /api/endpoint/suggestions/{suggestion_type}` endpoint. +* Remove references to `GET /api/endpoint/action_log/{agent_id}` endpoint. +* Remove references to `GET /api/endpoint/metadata/transforms` endpoint. +* Replace references to deprecated endpoints with the replacements listed in the breaking change details. +-- +==== [discrete] [[breaking-201550]] diff --git a/docs/user/alerting/alerting-setup.asciidoc b/docs/user/alerting/alerting-setup.asciidoc index b3af9bfbe0303..a5a529eb016f4 100644 --- a/docs/user/alerting/alerting-setup.asciidoc +++ b/docs/user/alerting/alerting-setup.asciidoc @@ -64,10 +64,11 @@ a| ==== The *{connectors-feature}* feature privilege is required to manage connectors. To add rule actions and test connectors, you require only `Read` privileges. +By default, `All` privileges include authority to run {endpoint-sec} connectors (such as SentinelOne and CrowdStrike) unless you customize the sub-feature privileges. -By default, `All` privileges for the *Rules Settings* feature include authority to edit flapping detection settings unless you customize the sub-feature privileges. +Likewise, you can customize the *Rules Settings* sub-feature privileges related to flapping detection settings. -preview:[] To create a rule that uses the <>, you must also have `all` privileges for the *Cases* feature. +To create a rule that uses the <>, you must also have `All` privileges for the *Cases* feature. The rule type also affects the privileges that are required. For example, to create or edit {ml} rules, you must have `all` privileges for the *Analytics > {ml-app}* feature. diff --git a/docs/user/reporting/reporting-csv-troubleshooting.asciidoc b/docs/user/reporting/reporting-csv-troubleshooting.asciidoc index f0edec18bd8e5..21ca7b721d85a 100644 --- a/docs/user/reporting/reporting-csv-troubleshooting.asciidoc +++ b/docs/user/reporting/reporting-csv-troubleshooting.asciidoc @@ -69,6 +69,21 @@ Such changes aren't guaranteed to solve the issue, but give the functionality a chance of working in this use case. Unfortunately, lowering the scroll size will require more requests to Elasticsearch during export, which adds more time overhead, which could unintentionally create more instances of auth token expiration errors. +[float] +[[reporting-troubleshooting-inspect-query-used-for-export]] +=== Inspecting the query used for CSV export + +The listing of reports in *Stack Management > Reporting* allows you to inspect the query used for CSV export. It can be helpful to see the raw responses +from Elasticsearch, or determine if there are performance improvements to be gained by changing the way you query the data. + +1. Go to **Stack Management > Reporting** and click the info icon next to a report. +2. In the footer of the report flyout, click **Actions**. +3. Click **Inspect query in Console** in the **Actions** menu. +4. This will open the *Console* application, pre-filled with the queries used to generate the CSV export. + +[role="screenshot"] +image::https://images.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt4758e67aaec715d9/67897d0be92e090a6dc626a8/inspect-query-from-csv-export.gif[Inspect the query used for CSV export] + [float] [[reporting-troubleshooting-csv-token-expired]] === Token expiration diff --git a/examples/controls_example/public/app/react_control_example/serialized_control_group_state.ts b/examples/controls_example/public/app/react_control_example/serialized_control_group_state.ts index 3d6487cdc7cba..c9c7609d6ad1d 100644 --- a/examples/controls_example/public/app/react_control_example/serialized_control_group_state.ts +++ b/examples/controls_example/public/app/react_control_example/serialized_control_group_state.ts @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import type { SerializedPanelState } from '@kbn/presentation-containers'; +import type { SerializedPanelState } from '@kbn/presentation-publishing'; import type { ControlGroupSerializedState } from '@kbn/controls-plugin/common'; import { OPTIONS_LIST_CONTROL, diff --git a/examples/embeddable_examples/public/app/presentation_container_example/page_api.ts b/examples/embeddable_examples/public/app/presentation_container_example/page_api.ts index c08ba7a499b98..1e06c5cb62b5b 100644 --- a/examples/embeddable_examples/public/app/presentation_container_example/page_api.ts +++ b/examples/embeddable_examples/public/app/presentation_container_example/page_api.ts @@ -12,7 +12,6 @@ import { v4 as generateId } from 'uuid'; import { TimeRange } from '@kbn/es-query'; import { PanelPackage, - apiHasSerializableState, childrenUnsavedChanges$, combineCompatibleChildrenApis, } from '@kbn/presentation-containers'; @@ -21,6 +20,7 @@ import { PublishesDataLoading, PublishingSubject, ViewMode, + apiHasSerializableState, apiPublishesDataLoading, apiPublishesUnsavedChanges, } from '@kbn/presentation-publishing'; diff --git a/examples/embeddable_examples/public/app/presentation_container_example/types.ts b/examples/embeddable_examples/public/app/presentation_container_example/types.ts index c3530ba71dbcf..bcd3c0b9fcb52 100644 --- a/examples/embeddable_examples/public/app/presentation_container_example/types.ts +++ b/examples/embeddable_examples/public/app/presentation_container_example/types.ts @@ -13,7 +13,6 @@ import { HasSerializedChildState, HasRuntimeChildState, PresentationContainer, - SerializedPanelState, HasSaveNotification, } from '@kbn/presentation-containers'; import { @@ -21,6 +20,7 @@ import { PublishesDataLoading, PublishesTimeRange, PublishesUnsavedChanges, + SerializedPanelState, PublishesViewMode, } from '@kbn/presentation-publishing'; import { PublishesReload } from '@kbn/presentation-publishing/interfaces/fetch/publishes_reload'; diff --git a/examples/embeddable_examples/public/app/state_management_example/last_saved_state.ts b/examples/embeddable_examples/public/app/state_management_example/last_saved_state.ts index bf96dd6b809ac..1b8ba4e0f9209 100644 --- a/examples/embeddable_examples/public/app/state_management_example/last_saved_state.ts +++ b/examples/embeddable_examples/public/app/state_management_example/last_saved_state.ts @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { SerializedPanelState } from '@kbn/presentation-containers'; +import { SerializedPanelState } from '@kbn/presentation-publishing'; import { BookSerializedState } from '../../react_embeddables/saved_book/types'; const SAVED_STATE_SESSION_STORAGE_KEY = diff --git a/examples/embeddable_examples/public/react_embeddables/saved_book/saved_book_editor.tsx b/examples/embeddable_examples/public/react_embeddables/saved_book/saved_book_editor.tsx index 0222e682b7b0d..b83c84610c7c6 100644 --- a/examples/embeddable_examples/public/react_embeddables/saved_book/saved_book_editor.tsx +++ b/examples/embeddable_examples/public/react_embeddables/saved_book/saved_book_editor.tsx @@ -26,11 +26,7 @@ import { CoreStart } from '@kbn/core-lifecycle-browser'; import { OverlayRef } from '@kbn/core-mount-utils-browser'; import { i18n } from '@kbn/i18n'; import { tracksOverlays } from '@kbn/presentation-containers'; -import { - apiHasInPlaceLibraryTransforms, - apiHasUniqueId, - useBatchedOptionalPublishingSubjects, -} from '@kbn/presentation-publishing'; +import { apiHasUniqueId, useBatchedOptionalPublishingSubjects } from '@kbn/presentation-publishing'; import { toMountPoint } from '@kbn/react-kibana-mount'; import React, { useState } from 'react'; import { serializeBookAttributes } from './book_state'; @@ -74,7 +70,7 @@ export const openSavedBookEditor = ({ onSubmit={async (addToLibrary: boolean) => { const savedBookId = addToLibrary ? await saveBookAttributes( - apiHasInPlaceLibraryTransforms(api) ? api.libraryId$.value : undefined, + api?.getSavedBookId(), serializeBookAttributes(attributesManager) ) : undefined; @@ -114,15 +110,13 @@ export const SavedBookEditor = ({ onCancel: () => void; api?: BookApi; }) => { - const [libraryId, authorName, synopsis, bookTitle, numberOfPages] = - useBatchedOptionalPublishingSubjects( - api?.libraryId$, - attributesManager.authorName, - attributesManager.bookSynopsis, - attributesManager.bookTitle, - attributesManager.numberOfPages - ); - const [addToLibrary, setAddToLibrary] = useState(Boolean(libraryId)); + const [authorName, synopsis, bookTitle, numberOfPages] = useBatchedOptionalPublishingSubjects( + attributesManager.authorName, + attributesManager.bookSynopsis, + attributesManager.bookTitle, + attributesManager.numberOfPages + ); + const [addToLibrary, setAddToLibrary] = useState(Boolean(api?.getSavedBookId())); const [saving, setSaving] = useState(false); return ( diff --git a/examples/embeddable_examples/public/react_embeddables/saved_book/saved_book_react_embeddable.tsx b/examples/embeddable_examples/public/react_embeddables/saved_book/saved_book_react_embeddable.tsx index 1768330d218d5..d23029084b85a 100644 --- a/examples/embeddable_examples/public/react_embeddables/saved_book/saved_book_react_embeddable.tsx +++ b/examples/embeddable_examples/public/react_embeddables/saved_book/saved_book_react_embeddable.tsx @@ -22,12 +22,13 @@ import { ReactEmbeddableFactory } from '@kbn/embeddable-plugin/public'; import { i18n } from '@kbn/i18n'; import { apiHasParentApi, + getUnchangingComparator, initializeTitles, SerializedTitles, + SerializedPanelState, useBatchedPublishingSubjects, } from '@kbn/presentation-publishing'; import React from 'react'; -import { BehaviorSubject } from 'rxjs'; import { PresentationContainer } from '@kbn/presentation-containers'; import { serializeBookAttributes, stateManagerFromAttributes } from './book_state'; import { SAVED_BOOK_ID } from './constants'; @@ -82,7 +83,24 @@ export const getSavedBookEmbeddableFactory = (core: CoreStart) => { buildEmbeddable: async (state, buildApi) => { const { titlesApi, titleComparators, serializeTitles } = initializeTitles(state); const bookAttributesManager = stateManagerFromAttributes(state); - const savedBookId$ = new BehaviorSubject(state.savedBookId); + const isByReference = Boolean(state.savedBookId); + + const serializeBook = (byReference: boolean, newId?: string) => { + if (byReference) { + // if this book is currently by reference, we serialize the reference only. + const bookByReferenceState: BookByReferenceSerializedState = { + savedBookId: newId ?? state.savedBookId!, + ...serializeTitles(), + }; + return { rawState: bookByReferenceState }; + } + // if this book is currently by value, we serialize the entire state. + const bookByValueState: BookByValueSerializedState = { + attributes: serializeBookAttributes(bookAttributesManager), + ...serializeTitles(), + }; + return { rawState: bookByValueState }; + }; const api = buildApi( { @@ -95,7 +113,15 @@ export const getSavedBookEmbeddableFactory = (core: CoreStart) => { core, api, }).then((result) => { - savedBookId$.next(result.savedBookId); + const nextIsByReference = Boolean(result.savedBookId); + + // if the by reference state has changed during this edit, reinitialize the panel. + if (nextIsByReference !== isByReference) { + api.parentApi?.replacePanel(api.uuid, { + serializedState: serializeBook(nextIsByReference, result.savedBookId), + panelType: api.type, + }); + } }); }, isEditingEnabled: () => true, @@ -103,47 +129,28 @@ export const getSavedBookEmbeddableFactory = (core: CoreStart) => { i18n.translate('embeddableExamples.savedbook.editBook.displayName', { defaultMessage: 'book', }), - serializeState: () => { - if (!Boolean(savedBookId$.value)) { - // if this book is currently by value, we serialize the entire state. - const bookByValueState: BookByValueSerializedState = { - attributes: serializeBookAttributes(bookAttributesManager), - ...serializeTitles(), - }; - return { rawState: bookByValueState }; - } - - // if this book is currently by reference, we serialize the reference only. - const bookByReferenceState: BookByReferenceSerializedState = { - savedBookId: savedBookId$.value!, - ...serializeTitles(), - }; - return { rawState: bookByReferenceState }; - }, + serializeState: () => serializeBook(isByReference), - // in place library transforms - libraryId$: savedBookId$, + // library transforms + getSavedBookId: () => state.savedBookId, saveToLibrary: async (newTitle: string) => { bookAttributesManager.bookTitle.next(newTitle); const newId = await saveBookAttributes( undefined, serializeBookAttributes(bookAttributesManager) ); - savedBookId$.next(newId); return newId; }, checkForDuplicateTitle: async (title) => {}, - unlinkFromLibrary: () => { - savedBookId$.next(undefined); - }, - getByValueRuntimeSnapshot: () => { - const snapshot = api.snapshotRuntimeState(); - delete snapshot.savedBookId; - return snapshot; - }, + getSerializedStateByValue: () => + serializeBook(false) as SerializedPanelState, + getSerializedStateByReference: (newId) => + serializeBook(true, newId) as SerializedPanelState, + canLinkToLibrary: async () => !isByReference, + canUnlinkFromLibrary: async () => isByReference, }, { - savedBookId: [savedBookId$, (val) => savedBookId$.next(val)], + savedBookId: getUnchangingComparator(), // saved book id will not change over the lifetime of the embeddable. ...bookAttributesManager.comparators, ...titleComparators, } @@ -156,14 +163,12 @@ export const getSavedBookEmbeddableFactory = (core: CoreStart) => { return { api, Component: () => { - const [authorName, numberOfPages, savedBookId, bookTitle, synopsis] = - useBatchedPublishingSubjects( - bookAttributesManager.authorName, - bookAttributesManager.numberOfPages, - savedBookId$, - bookAttributesManager.bookTitle, - bookAttributesManager.bookSynopsis - ); + const [authorName, numberOfPages, bookTitle, synopsis] = useBatchedPublishingSubjects( + bookAttributesManager.authorName, + bookAttributesManager.numberOfPages, + bookAttributesManager.bookTitle, + bookAttributesManager.bookSynopsis + ); const { euiTheme } = useEuiTheme(); return ( @@ -177,7 +182,7 @@ export const getSavedBookEmbeddableFactory = (core: CoreStart) => { size="s" color={'warning'} title={ - savedBookId + isByReference ? i18n.translate('embeddableExamples.savedBook.libraryCallout', { defaultMessage: 'Saved in library', }) @@ -185,7 +190,7 @@ export const getSavedBookEmbeddableFactory = (core: CoreStart) => { defaultMessage: 'Not saved in library', }) } - iconType={savedBookId ? 'folderCheck' : 'folderClosed'} + iconType={isByReference ? 'folderCheck' : 'folderClosed'} /> )}
string | undefined; +} + export type BookSerializedState = SerializedTitles & (BookByValueSerializedState | BookByReferenceSerializedState); @@ -48,4 +52,5 @@ export interface BookRuntimeState export type BookApi = DefaultEmbeddableApi & HasEditCapabilities & - HasInPlaceLibraryTransforms; + HasLibraryTransforms & + HasSavedBookId; diff --git a/oas_docs/bundle.json b/oas_docs/bundle.json index e92dcdeb95d99..c72e872084b0f 100644 --- a/oas_docs/bundle.json +++ b/oas_docs/bundle.json @@ -9279,6 +9279,30 @@ }, "type": "array" }, + "agentless": { + "additionalProperties": false, + "properties": { + "resources": { + "additionalProperties": false, + "properties": { + "requests": { + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, "agents": { "type": "number" }, @@ -10062,6 +10086,30 @@ }, "type": "array" }, + "agentless": { + "additionalProperties": false, + "properties": { + "resources": { + "additionalProperties": false, + "properties": { + "requests": { + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, "data_output_id": { "nullable": true, "type": "string" @@ -10340,6 +10388,30 @@ }, "type": "array" }, + "agentless": { + "additionalProperties": false, + "properties": { + "resources": { + "additionalProperties": false, + "properties": { + "requests": { + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, "agents": { "type": "number" }, @@ -11149,6 +11221,30 @@ }, "type": "array" }, + "agentless": { + "additionalProperties": false, + "properties": { + "resources": { + "additionalProperties": false, + "properties": { + "requests": { + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, "agents": { "type": "number" }, @@ -12194,6 +12290,30 @@ }, "type": "array" }, + "agentless": { + "additionalProperties": false, + "properties": { + "resources": { + "additionalProperties": false, + "properties": { + "requests": { + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, "agents": { "type": "number" }, @@ -12975,6 +13095,30 @@ }, "type": "array" }, + "agentless": { + "additionalProperties": false, + "properties": { + "resources": { + "additionalProperties": false, + "properties": { + "requests": { + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, "data_output_id": { "nullable": true, "type": "string" @@ -13253,6 +13397,30 @@ }, "type": "array" }, + "agentless": { + "additionalProperties": false, + "properties": { + "resources": { + "additionalProperties": false, + "properties": { + "requests": { + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, "agents": { "type": "number" }, @@ -14062,6 +14230,30 @@ }, "type": "array" }, + "agentless": { + "additionalProperties": false, + "properties": { + "resources": { + "additionalProperties": false, + "properties": { + "requests": { + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, "agents": { "type": "number" }, @@ -14978,6 +15170,7 @@ "monitoring": { "additionalProperties": false, "properties": { + "apm": {}, "enabled": { "type": "boolean" }, @@ -15001,7 +15194,8 @@ "enabled", "metrics", "logs", - "traces" + "traces", + "apm" ], "type": "object" }, diff --git a/oas_docs/bundle.serverless.json b/oas_docs/bundle.serverless.json index 86fb7f356af1f..a1055afca8265 100644 --- a/oas_docs/bundle.serverless.json +++ b/oas_docs/bundle.serverless.json @@ -9279,6 +9279,30 @@ }, "type": "array" }, + "agentless": { + "additionalProperties": false, + "properties": { + "resources": { + "additionalProperties": false, + "properties": { + "requests": { + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, "agents": { "type": "number" }, @@ -10062,6 +10086,30 @@ }, "type": "array" }, + "agentless": { + "additionalProperties": false, + "properties": { + "resources": { + "additionalProperties": false, + "properties": { + "requests": { + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, "data_output_id": { "nullable": true, "type": "string" @@ -10340,6 +10388,30 @@ }, "type": "array" }, + "agentless": { + "additionalProperties": false, + "properties": { + "resources": { + "additionalProperties": false, + "properties": { + "requests": { + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, "agents": { "type": "number" }, @@ -11149,6 +11221,30 @@ }, "type": "array" }, + "agentless": { + "additionalProperties": false, + "properties": { + "resources": { + "additionalProperties": false, + "properties": { + "requests": { + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, "agents": { "type": "number" }, @@ -12194,6 +12290,30 @@ }, "type": "array" }, + "agentless": { + "additionalProperties": false, + "properties": { + "resources": { + "additionalProperties": false, + "properties": { + "requests": { + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, "agents": { "type": "number" }, @@ -12975,6 +13095,30 @@ }, "type": "array" }, + "agentless": { + "additionalProperties": false, + "properties": { + "resources": { + "additionalProperties": false, + "properties": { + "requests": { + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, "data_output_id": { "nullable": true, "type": "string" @@ -13253,6 +13397,30 @@ }, "type": "array" }, + "agentless": { + "additionalProperties": false, + "properties": { + "resources": { + "additionalProperties": false, + "properties": { + "requests": { + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, "agents": { "type": "number" }, @@ -14062,6 +14230,30 @@ }, "type": "array" }, + "agentless": { + "additionalProperties": false, + "properties": { + "resources": { + "additionalProperties": false, + "properties": { + "requests": { + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, "agents": { "type": "number" }, @@ -14978,6 +15170,7 @@ "monitoring": { "additionalProperties": false, "properties": { + "apm": {}, "enabled": { "type": "boolean" }, @@ -15001,7 +15194,8 @@ "enabled", "metrics", "logs", - "traces" + "traces", + "apm" ], "type": "object" }, diff --git a/oas_docs/output/kibana.serverless.yaml b/oas_docs/output/kibana.serverless.yaml index bc71cc8f16492..4d574192cb676 100644 --- a/oas_docs/output/kibana.serverless.yaml +++ b/oas_docs/output/kibana.serverless.yaml @@ -12877,6 +12877,22 @@ paths: - name - enabled type: array + agentless: + additionalProperties: false + type: object + properties: + resources: + additionalProperties: false + type: object + properties: + requests: + additionalProperties: false + type: object + properties: + cpu: + type: string + memory: + type: string agents: type: number data_output_id: @@ -13421,6 +13437,22 @@ paths: - name - enabled type: array + agentless: + additionalProperties: false + type: object + properties: + resources: + additionalProperties: false + type: object + properties: + requests: + additionalProperties: false + type: object + properties: + cpu: + type: string + memory: + type: string data_output_id: nullable: true type: string @@ -13616,6 +13648,22 @@ paths: - name - enabled type: array + agentless: + additionalProperties: false + type: object + properties: + resources: + additionalProperties: false + type: object + properties: + requests: + additionalProperties: false + type: object + properties: + cpu: + type: string + memory: + type: string agents: type: number data_output_id: @@ -14179,6 +14227,22 @@ paths: - name - enabled type: array + agentless: + additionalProperties: false + type: object + properties: + resources: + additionalProperties: false + type: object + properties: + requests: + additionalProperties: false + type: object + properties: + cpu: + type: string + memory: + type: string agents: type: number data_output_id: @@ -14721,6 +14785,22 @@ paths: - name - enabled type: array + agentless: + additionalProperties: false + type: object + properties: + resources: + additionalProperties: false + type: object + properties: + requests: + additionalProperties: false + type: object + properties: + cpu: + type: string + memory: + type: string agents: type: number data_output_id: @@ -15263,6 +15343,22 @@ paths: - name - enabled type: array + agentless: + additionalProperties: false + type: object + properties: + resources: + additionalProperties: false + type: object + properties: + requests: + additionalProperties: false + type: object + properties: + cpu: + type: string + memory: + type: string data_output_id: nullable: true type: string @@ -15458,6 +15554,22 @@ paths: - name - enabled type: array + agentless: + additionalProperties: false + type: object + properties: + resources: + additionalProperties: false + type: object + properties: + requests: + additionalProperties: false + type: object + properties: + cpu: + type: string + memory: + type: string agents: type: number data_output_id: @@ -16020,6 +16132,22 @@ paths: - name - enabled type: array + agentless: + additionalProperties: false + type: object + properties: + resources: + additionalProperties: false + type: object + properties: + requests: + additionalProperties: false + type: object + properties: + cpu: + type: string + memory: + type: string agents: type: number data_output_id: @@ -16652,6 +16780,7 @@ paths: additionalProperties: false type: object properties: + apm: {} enabled: type: boolean logs: @@ -16669,6 +16798,7 @@ paths: - metrics - logs - traces + - apm protection: additionalProperties: false type: object diff --git a/oas_docs/output/kibana.yaml b/oas_docs/output/kibana.yaml index 6da35aa7e60c6..98319048fac28 100644 --- a/oas_docs/output/kibana.yaml +++ b/oas_docs/output/kibana.yaml @@ -15018,6 +15018,22 @@ paths: - name - enabled type: array + agentless: + additionalProperties: false + type: object + properties: + resources: + additionalProperties: false + type: object + properties: + requests: + additionalProperties: false + type: object + properties: + cpu: + type: string + memory: + type: string agents: type: number data_output_id: @@ -15561,6 +15577,22 @@ paths: - name - enabled type: array + agentless: + additionalProperties: false + type: object + properties: + resources: + additionalProperties: false + type: object + properties: + requests: + additionalProperties: false + type: object + properties: + cpu: + type: string + memory: + type: string data_output_id: nullable: true type: string @@ -15756,6 +15788,22 @@ paths: - name - enabled type: array + agentless: + additionalProperties: false + type: object + properties: + resources: + additionalProperties: false + type: object + properties: + requests: + additionalProperties: false + type: object + properties: + cpu: + type: string + memory: + type: string agents: type: number data_output_id: @@ -16318,6 +16366,22 @@ paths: - name - enabled type: array + agentless: + additionalProperties: false + type: object + properties: + resources: + additionalProperties: false + type: object + properties: + requests: + additionalProperties: false + type: object + properties: + cpu: + type: string + memory: + type: string agents: type: number data_output_id: @@ -16859,6 +16923,22 @@ paths: - name - enabled type: array + agentless: + additionalProperties: false + type: object + properties: + resources: + additionalProperties: false + type: object + properties: + requests: + additionalProperties: false + type: object + properties: + cpu: + type: string + memory: + type: string agents: type: number data_output_id: @@ -17400,6 +17480,22 @@ paths: - name - enabled type: array + agentless: + additionalProperties: false + type: object + properties: + resources: + additionalProperties: false + type: object + properties: + requests: + additionalProperties: false + type: object + properties: + cpu: + type: string + memory: + type: string data_output_id: nullable: true type: string @@ -17595,6 +17691,22 @@ paths: - name - enabled type: array + agentless: + additionalProperties: false + type: object + properties: + resources: + additionalProperties: false + type: object + properties: + requests: + additionalProperties: false + type: object + properties: + cpu: + type: string + memory: + type: string agents: type: number data_output_id: @@ -18156,6 +18268,22 @@ paths: - name - enabled type: array + agentless: + additionalProperties: false + type: object + properties: + resources: + additionalProperties: false + type: object + properties: + requests: + additionalProperties: false + type: object + properties: + cpu: + type: string + memory: + type: string agents: type: number data_output_id: @@ -18786,6 +18914,7 @@ paths: additionalProperties: false type: object properties: + apm: {} enabled: type: boolean logs: @@ -18803,6 +18932,7 @@ paths: - metrics - logs - traces + - apm protection: additionalProperties: false type: object diff --git a/package.json b/package.json index bf066aab91fc9..8debfdf0d27d0 100644 --- a/package.json +++ b/package.json @@ -1093,7 +1093,7 @@ "css-box-model": "^1.2.1", "css.escape": "^1.5.1", "cypress-data-session": "^2.8.0", - "cytoscape": "^3.30.4", + "cytoscape": "^3.31.0", "cytoscape-dagre": "^2.5.0", "d3": "3.5.17", "d3-array": "2.12.1", @@ -1117,7 +1117,7 @@ "expiry-js": "0.1.7", "exponential-backoff": "^3.1.1", "extract-zip": "^2.0.1", - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", "fast-glob": "^3.3.2", "fastest-levenshtein": "^1.0.16", "fflate": "^0.6.9", @@ -1186,8 +1186,8 @@ "nodemailer": "^6.9.15", "normalize-path": "^3.0.0", "nunjucks": "^3.2.4", - "oas": "^25.2.0", - "object-hash": "^1.3.1", + "oas": "^25.2.1", + "object-hash": "^3.0.0", "object-path-immutable": "^3.1.1", "openai": "^4.72.0", "openpgp": "5.10.1", @@ -1276,7 +1276,7 @@ "use-resize-observer": "^9.1.0", "usng.js": "^0.4.5", "utility-types": "^3.10.0", - "uuid": "9.0.0", + "uuid": "10.0.0", "vega": "^5.24.0", "vega-interpreter": "^1.0.4", "vega-lite": "^5.5.0", @@ -1564,7 +1564,6 @@ "@types/cli-progress": "^3.11.5", "@types/color": "^3.0.3", "@types/cssstyle": "^2.2.4", - "@types/cytoscape": "^3.21.8", "@types/d3": "^3.5.43", "@types/d3-array": "^2.12.1", "@types/d3-brush": "^3.0.0", @@ -1608,7 +1607,7 @@ "@types/jsonwebtoken": "^9.0.0", "@types/license-checker": "15.0.0", "@types/loader-utils": "^2.0.3", - "@types/lodash": "^4.17.13", + "@types/lodash": "^4.17.14", "@types/lru-cache": "^5.1.0", "@types/lz-string": "^1.3.34", "@types/mapbox__vector-tile": "1.3.0", @@ -1628,7 +1627,7 @@ "@types/nodemailer": "^6.4.0", "@types/normalize-path": "^3.0.0", "@types/nunjucks": "^3.2.6", - "@types/object-hash": "^1.3.0", + "@types/object-hash": "^3.0.6", "@types/ora": "^1.3.5", "@types/papaparse": "^5.0.3", "@types/pbf": "3.0.2", @@ -1664,7 +1663,7 @@ "@types/tinycolor2": "^1.4.1", "@types/tough-cookie": "^4.0.5", "@types/type-detect": "^4.0.1", - "@types/uuid": "^9.0.0", + "@types/uuid": "^10.0.0", "@types/vinyl": "^2.0.4", "@types/vinyl-fs": "^3.0.2", "@types/watchpack": "^1.1.5", @@ -1720,7 +1719,7 @@ "cypress-recurse": "^1.35.2", "date-fns": "^2.29.3", "dependency-check": "^4.1.0", - "dependency-cruiser": "^16.4.2", + "dependency-cruiser": "^16.8.0", "ejs": "^3.1.10", "enzyme": "^3.11.0", "enzyme-to-json": "^3.6.2", @@ -1784,7 +1783,7 @@ "marge": "^1.0.1", "micromatch": "^4.0.8", "mini-css-extract-plugin": "1.1.0", - "minimist": "^1.2.6", + "minimist": "^1.2.8", "mocha": "^10.3.0", "mocha-junit-reporter": "^2.0.2", "mocha-multi-reporters": "^1.5.1", diff --git a/packages/core/theme/core-theme-browser-mocks/src/theme_service.mock.ts b/packages/core/theme/core-theme-browser-mocks/src/theme_service.mock.ts index e3d2b66645794..8c27cc8561cf7 100644 --- a/packages/core/theme/core-theme-browser-mocks/src/theme_service.mock.ts +++ b/packages/core/theme/core-theme-browser-mocks/src/theme_service.mock.ts @@ -14,7 +14,7 @@ import type { ThemeService } from '@kbn/core-theme-browser-internal'; const mockTheme: CoreTheme = { darkMode: false, - name: 'amsterdam', + name: 'borealis', }; const createThemeMock = (): CoreTheme => { diff --git a/packages/kbn-apm-synthtrace-client/src/lib/apm/apm_fields.ts b/packages/kbn-apm-synthtrace-client/src/lib/apm/apm_fields.ts index 3371cc27227cb..811a78c5d545c 100644 --- a/packages/kbn-apm-synthtrace-client/src/lib/apm/apm_fields.ts +++ b/packages/kbn-apm-synthtrace-client/src/lib/apm/apm_fields.ts @@ -213,6 +213,7 @@ export type ApmFields = Fields<{ }>; 'url.original': string; 'url.domain': string; + 'url.full': string; }> & ApmApplicationMetricFields & ExperimentalFields; diff --git a/packages/kbn-apm-synthtrace-client/src/lib/apm/transaction.ts b/packages/kbn-apm-synthtrace-client/src/lib/apm/transaction.ts index 3f3f15e1d22b0..a5b3811887c6d 100644 --- a/packages/kbn-apm-synthtrace-client/src/lib/apm/transaction.ts +++ b/packages/kbn-apm-synthtrace-client/src/lib/apm/transaction.ts @@ -25,6 +25,9 @@ export class Transaction extends BaseSpan { 'processor.event': 'transaction', 'transaction.id': generateShortId(), 'transaction.sampled': true, + 'http.request.method': 'GET', + 'http.response.status_code': 200, + 'url.full': 'elastic.co', }); } diff --git a/packages/kbn-apm-synthtrace-client/src/lib/otel/index.ts b/packages/kbn-apm-synthtrace-client/src/lib/otel/index.ts index dfa3f10d8fa6f..43d159a632203 100644 --- a/packages/kbn-apm-synthtrace-client/src/lib/otel/index.ts +++ b/packages/kbn-apm-synthtrace-client/src/lib/otel/index.ts @@ -22,7 +22,6 @@ interface OtelSharedResourceAttributes { 'telemetry.sdk.language'?: string; 'telemetry.sdk.name'?: string; 'telemetry.sdk.version'?: string; - 'some.resource.attribute'?: string; } export interface OtelDocument extends Fields { @@ -165,6 +164,9 @@ class Otel extends Serializable { 'transaction.root': true, 'transaction.sampled': true, 'transaction.type': 'unknown', + 'http.request.method': 'POST', + 'http.response.status_code': 200, + 'url.full': 'elastic.co', }, data_stream: { dataset: 'generic.otel', diff --git a/packages/kbn-apm-synthtrace-client/src/lib/otel/transaction.ts b/packages/kbn-apm-synthtrace-client/src/lib/otel/transaction.ts index d6f7c7111b187..0953028f2e008 100644 --- a/packages/kbn-apm-synthtrace-client/src/lib/otel/transaction.ts +++ b/packages/kbn-apm-synthtrace-client/src/lib/otel/transaction.ts @@ -24,6 +24,9 @@ export interface OtelTransactionDocument extends OtelDocument { 'transaction.root'?: boolean; 'transaction.sampled'?: boolean; 'transaction.type'?: string; + 'http.response.status_code'?: number; + 'http.request.method'?: string; + 'url.full'?: string; }; status?: { code?: string; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/logs_only.ts b/packages/kbn-apm-synthtrace/src/scenarios/logs_only.ts new file mode 100644 index 0000000000000..3c8838544d704 --- /dev/null +++ b/packages/kbn-apm-synthtrace/src/scenarios/logs_only.ts @@ -0,0 +1,79 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { LogDocument, log, generateShortId, generateLongId } from '@kbn/apm-synthtrace-client'; +import { Scenario } from '../cli/scenario'; +import { withClient } from '../lib/utils/with_client'; +import { parseLogsScenarioOpts } from './helpers/logs_scenario_opts_parser'; +import { IndexTemplateName } from '../lib/logs/custom_logsdb_index_templates'; +import { getCluster, getCloudRegion, getCloudProvider } from './helpers/logs_mock_data'; + +const MESSAGE_LOG_LEVELS = [ + { message: 'A simple log', level: 'info' }, + { message: 'Yet another debug log', level: 'debug' }, + { message: 'Error with certificate: "ca_trusted_fingerprint"', level: 'error' }, +]; + +const scenario: Scenario = async (runOptions) => { + const { isLogsDb } = parseLogsScenarioOpts(runOptions.scenarioOpts); + + return { + bootstrap: async ({ logsEsClient }) => { + if (isLogsDb) await logsEsClient.createIndexTemplate(IndexTemplateName.LogsDb); + }, + generate: ({ range, clients: { logsEsClient } }) => { + const { logger } = runOptions; + + const SERVICE_NAMES = Array(3) + .fill(null) + .map((_, idx) => `synth-service-logs-${idx}`); + + const logs = range + .interval('1m') + .rate(1) + .generator((timestamp) => { + return Array(20) + .fill(0) + .map(() => { + const index = Math.floor(Math.random() * 3); + const { clusterId, clusterName } = getCluster(index); + const cloudRegion = getCloudRegion(index); + return log + .create({ isLogsDb }) + .message(MESSAGE_LOG_LEVELS[index].message) + .logLevel(MESSAGE_LOG_LEVELS[index].level) + .service(SERVICE_NAMES[index]) + .defaults({ + 'trace.id': generateShortId(), + 'agent.name': 'synth-agent', + 'orchestrator.cluster.name': clusterName, + 'orchestrator.cluster.id': clusterId, + 'orchestrator.resource.id': generateShortId(), + 'cloud.provider': getCloudProvider(), + 'cloud.region': cloudRegion, + 'cloud.availability_zone': `${cloudRegion}a`, + 'cloud.project.id': generateShortId(), + 'cloud.instance.id': generateShortId(), + 'log.file.path': `/logs/${generateLongId()}/error.txt`, + }) + .timestamp(timestamp); + }); + }); + + return [ + withClient( + logsEsClient, + logger.perf('generating_logs', () => logs) + ), + ]; + }, + }; +}; + +export default scenario; diff --git a/packages/kbn-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts b/packages/kbn-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts index 8d1be5e0256dd..692a96df1cad3 100644 --- a/packages/kbn-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts +++ b/packages/kbn-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts @@ -95,6 +95,8 @@ describe('simple trace', () => { 'container.id': 'instance-1', 'event.outcome': 'success', 'host.name': 'instance-1', + 'http.request.method': 'GET', + 'http.response.status_code': 200, 'processor.event': 'transaction', 'processor.name': 'transaction', 'service.environment': 'production', @@ -107,6 +109,7 @@ describe('simple trace', () => { 'transaction.name': 'GET /api/product/list', 'transaction.type': 'request', 'transaction.sampled': true, + 'url.full': 'elastic.co', }); }); diff --git a/packages/kbn-apm-synthtrace/src/test/scenarios/__snapshots__/01_simple_trace.test.ts.snap b/packages/kbn-apm-synthtrace/src/test/scenarios/__snapshots__/01_simple_trace.test.ts.snap index f318942f397b3..ac84c00d38ad1 100644 --- a/packages/kbn-apm-synthtrace/src/test/scenarios/__snapshots__/01_simple_trace.test.ts.snap +++ b/packages/kbn-apm-synthtrace/src/test/scenarios/__snapshots__/01_simple_trace.test.ts.snap @@ -8,6 +8,8 @@ Array [ "container.id": "instance-1", "event.outcome": "success", "host.name": "instance-1", + "http.request.method": "GET", + "http.response.status_code": 200, "processor.event": "transaction", "processor.name": "transaction", "service.environment": "production", @@ -20,6 +22,7 @@ Array [ "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", + "url.full": "elastic.co", }, Object { "@timestamp": 1609459200050, @@ -89,6 +92,8 @@ Array [ "container.id": "instance-1", "event.outcome": "success", "host.name": "instance-1", + "http.request.method": "GET", + "http.response.status_code": 200, "processor.event": "transaction", "processor.name": "transaction", "service.environment": "production", @@ -101,6 +106,7 @@ Array [ "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", + "url.full": "elastic.co", }, Object { "@timestamp": 1609459260050, @@ -170,6 +176,8 @@ Array [ "container.id": "instance-1", "event.outcome": "success", "host.name": "instance-1", + "http.request.method": "GET", + "http.response.status_code": 200, "processor.event": "transaction", "processor.name": "transaction", "service.environment": "production", @@ -182,6 +190,7 @@ Array [ "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", + "url.full": "elastic.co", }, Object { "@timestamp": 1609459320050, @@ -251,6 +260,8 @@ Array [ "container.id": "instance-1", "event.outcome": "success", "host.name": "instance-1", + "http.request.method": "GET", + "http.response.status_code": 200, "processor.event": "transaction", "processor.name": "transaction", "service.environment": "production", @@ -263,6 +274,7 @@ Array [ "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", + "url.full": "elastic.co", }, Object { "@timestamp": 1609459380050, @@ -332,6 +344,8 @@ Array [ "container.id": "instance-1", "event.outcome": "success", "host.name": "instance-1", + "http.request.method": "GET", + "http.response.status_code": 200, "processor.event": "transaction", "processor.name": "transaction", "service.environment": "production", @@ -344,6 +358,7 @@ Array [ "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", + "url.full": "elastic.co", }, Object { "@timestamp": 1609459440050, @@ -413,6 +428,8 @@ Array [ "container.id": "instance-1", "event.outcome": "success", "host.name": "instance-1", + "http.request.method": "GET", + "http.response.status_code": 200, "processor.event": "transaction", "processor.name": "transaction", "service.environment": "production", @@ -425,6 +442,7 @@ Array [ "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", + "url.full": "elastic.co", }, Object { "@timestamp": 1609459500050, @@ -494,6 +512,8 @@ Array [ "container.id": "instance-1", "event.outcome": "success", "host.name": "instance-1", + "http.request.method": "GET", + "http.response.status_code": 200, "processor.event": "transaction", "processor.name": "transaction", "service.environment": "production", @@ -506,6 +526,7 @@ Array [ "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", + "url.full": "elastic.co", }, Object { "@timestamp": 1609459560050, @@ -575,6 +596,8 @@ Array [ "container.id": "instance-1", "event.outcome": "success", "host.name": "instance-1", + "http.request.method": "GET", + "http.response.status_code": 200, "processor.event": "transaction", "processor.name": "transaction", "service.environment": "production", @@ -587,6 +610,7 @@ Array [ "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", + "url.full": "elastic.co", }, Object { "@timestamp": 1609459620050, @@ -656,6 +680,8 @@ Array [ "container.id": "instance-1", "event.outcome": "success", "host.name": "instance-1", + "http.request.method": "GET", + "http.response.status_code": 200, "processor.event": "transaction", "processor.name": "transaction", "service.environment": "production", @@ -668,6 +694,7 @@ Array [ "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", + "url.full": "elastic.co", }, Object { "@timestamp": 1609459680050, @@ -737,6 +764,8 @@ Array [ "container.id": "instance-1", "event.outcome": "success", "host.name": "instance-1", + "http.request.method": "GET", + "http.response.status_code": 200, "processor.event": "transaction", "processor.name": "transaction", "service.environment": "production", @@ -749,6 +778,7 @@ Array [ "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", + "url.full": "elastic.co", }, Object { "@timestamp": 1609459740050, @@ -818,6 +848,8 @@ Array [ "container.id": "instance-1", "event.outcome": "success", "host.name": "instance-1", + "http.request.method": "GET", + "http.response.status_code": 200, "processor.event": "transaction", "processor.name": "transaction", "service.environment": "production", @@ -830,6 +862,7 @@ Array [ "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", + "url.full": "elastic.co", }, Object { "@timestamp": 1609459800050, @@ -899,6 +932,8 @@ Array [ "container.id": "instance-1", "event.outcome": "success", "host.name": "instance-1", + "http.request.method": "GET", + "http.response.status_code": 200, "processor.event": "transaction", "processor.name": "transaction", "service.environment": "production", @@ -911,6 +946,7 @@ Array [ "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", + "url.full": "elastic.co", }, Object { "@timestamp": 1609459860050, @@ -980,6 +1016,8 @@ Array [ "container.id": "instance-1", "event.outcome": "success", "host.name": "instance-1", + "http.request.method": "GET", + "http.response.status_code": 200, "processor.event": "transaction", "processor.name": "transaction", "service.environment": "production", @@ -992,6 +1030,7 @@ Array [ "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", + "url.full": "elastic.co", }, Object { "@timestamp": 1609459920050, @@ -1061,6 +1100,8 @@ Array [ "container.id": "instance-1", "event.outcome": "success", "host.name": "instance-1", + "http.request.method": "GET", + "http.response.status_code": 200, "processor.event": "transaction", "processor.name": "transaction", "service.environment": "production", @@ -1073,6 +1114,7 @@ Array [ "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", + "url.full": "elastic.co", }, Object { "@timestamp": 1609459980050, @@ -1142,6 +1184,8 @@ Array [ "container.id": "instance-1", "event.outcome": "success", "host.name": "instance-1", + "http.request.method": "GET", + "http.response.status_code": 200, "processor.event": "transaction", "processor.name": "transaction", "service.environment": "production", @@ -1154,6 +1198,7 @@ Array [ "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", + "url.full": "elastic.co", }, Object { "@timestamp": 1609460040050, diff --git a/packages/kbn-check-mappings-update-cli/current_fields.json b/packages/kbn-check-mappings-update-cli/current_fields.json index f14b11d4f6e36..fcb6a89e3284a 100644 --- a/packages/kbn-check-mappings-update-cli/current_fields.json +++ b/packages/kbn-check-mappings-update-cli/current_fields.json @@ -481,6 +481,7 @@ "agent_features", "agent_features.enabled", "agent_features.name", + "agentless", "data_output_id", "description", "download_source_id", @@ -601,6 +602,7 @@ "agent_features", "agent_features.enabled", "agent_features.name", + "agentless", "data_output_id", "description", "download_source_id", diff --git a/packages/kbn-check-mappings-update-cli/current_mappings.json b/packages/kbn-check-mappings-update-cli/current_mappings.json index 22a0760ea4d8a..fc76793d4223f 100644 --- a/packages/kbn-check-mappings-update-cli/current_mappings.json +++ b/packages/kbn-check-mappings-update-cli/current_mappings.json @@ -1624,6 +1624,10 @@ } } }, + "agentless": { + "dynamic": false, + "properties": {} + }, "data_output_id": { "type": "keyword" }, @@ -1994,6 +1998,10 @@ } } }, + "agentless": { + "dynamic": false, + "properties": {} + }, "data_output_id": { "type": "keyword" }, diff --git a/packages/kbn-es/src/serverless_resources/project_roles/security/roles.yml b/packages/kbn-es/src/serverless_resources/project_roles/security/roles.yml index 4993c4552eb88..0a4bc4878023e 100644 --- a/packages/kbn-es/src/serverless_resources/project_roles/security/roles.yml +++ b/packages/kbn-es/src/serverless_resources/project_roles/security/roles.yml @@ -43,12 +43,14 @@ viewer: - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.read - - feature_siem.read_alerts - - feature_siem.endpoint_list_read + - feature_siemV2.read + - feature_siemV2.read_alerts + - feature_siemV2.endpoint_list_read - feature_securitySolutionCasesV2.read - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.read + - feature_securitySolutionNotes.read - feature_actions.read - feature_builtInAlerts.read - feature_osquery.read @@ -113,22 +115,24 @@ editor: - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all - - feature_siem.policy_management_read # Elastic Defend Policy Management - - feature_siem.host_isolation_all - - feature_siem.process_operations_all - - feature_siem.actions_log_management_all # Response actions history - - feature_siem.file_operations_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all + - feature_siemV2.policy_management_read # Elastic Defend Policy Management + - feature_siemV2.host_isolation_all + - feature_siemV2.process_operations_all + - feature_siemV2.actions_log_management_all # Response actions history + - feature_siemV2.file_operations_all - feature_securitySolutionCasesV2.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.read - feature_builtInAlerts.all - feature_osquery.all @@ -174,12 +178,14 @@ t1_analyst: - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.read - - feature_siem.read_alerts - - feature_siem.endpoint_list_read + - feature_siemV2.read + - feature_siemV2.read_alerts + - feature_siemV2.endpoint_list_read - feature_securitySolutionCasesV2.read - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.read + - feature_securitySolutionNotes.read - feature_actions.read - feature_builtInAlerts.read - feature_osquery.read @@ -229,12 +235,14 @@ t2_analyst: - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.read - - feature_siem.read_alerts - - feature_siem.endpoint_list_read + - feature_siemV2.read + - feature_siemV2.read_alerts + - feature_siemV2.endpoint_list_read - feature_securitySolutionCasesV2.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.read + - feature_securitySolutionNotes.read - feature_actions.read - feature_builtInAlerts.read - feature_osquery.read @@ -289,24 +297,26 @@ t3_analyst: - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all - - feature_siem.policy_management_read # Elastic Defend Policy Management - - feature_siem.host_isolation_all - - feature_siem.process_operations_all - - feature_siem.actions_log_management_all # Response actions history - - feature_siem.file_operations_all - - feature_siem.scan_operations_all - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all + - feature_siemV2.policy_management_read # Elastic Defend Policy Management + - feature_siemV2.host_isolation_all + - feature_siemV2.process_operations_all + - feature_siemV2.actions_log_management_all # Response actions history + - feature_siemV2.file_operations_all + - feature_siemV2.scan_operations_all + - feature_siemV2.workflow_insights_all - feature_securitySolutionCasesV2.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.read - feature_builtInAlerts.all - feature_osquery.all @@ -363,12 +373,14 @@ threat_intelligence_analyst: - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.all - - feature_siem.endpoint_list_read - - feature_siem.blocklist_all + - feature_siemV2.all + - feature_siemV2.endpoint_list_read + - feature_siemV2.blocklist_all - feature_securitySolutionCasesV2.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.read - feature_builtInAlerts.read - feature_osquery.all @@ -424,20 +436,22 @@ rule_author: - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.policy_management_all - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_read - - feature_siem.blocklist_all # Elastic Defend Policy Management - - feature_siem.actions_log_management_read - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.policy_management_all + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_read + - feature_siemV2.blocklist_all # Elastic Defend Policy Management + - feature_siemV2.actions_log_management_read + - feature_siemV2.workflow_insights_all - feature_securitySolutionCasesV2.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.read - feature_builtInAlerts.all - feature_osquery.all @@ -493,25 +507,27 @@ soc_manager: - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.policy_management_all - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all - - feature_siem.host_isolation_all - - feature_siem.process_operations_all - - feature_siem.actions_log_management_all - - feature_siem.file_operations_all - - feature_siem.execute_operations_all - - feature_siem.scan_operations_all - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.policy_management_all + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all + - feature_siemV2.host_isolation_all + - feature_siemV2.process_operations_all + - feature_siemV2.actions_log_management_all + - feature_siemV2.file_operations_all + - feature_siemV2.execute_operations_all + - feature_siemV2.scan_operations_all + - feature_siemV2.workflow_insights_all - feature_securitySolutionCasesV2.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all @@ -566,12 +582,14 @@ detections_admin: - application: 'kibana-.kibana' privileges: - feature_ml.all - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts - feature_securitySolutionCasesV2.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.all - feature_builtInAlerts.all - feature_dev_tools.all @@ -618,20 +636,22 @@ platform_engineer: - application: 'kibana-.kibana' privileges: - feature_ml.all - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.policy_management_all - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all # Elastic Defend Policy Management - - feature_siem.actions_log_management_read - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.policy_management_all + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all # Elastic Defend Policy Management + - feature_siemV2.actions_log_management_read + - feature_siemV2.workflow_insights_all - feature_securitySolutionCasesV2.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.all - feature_builtInAlerts.all - feature_fleet.all @@ -688,24 +708,26 @@ endpoint_operations_analyst: - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.policy_management_all - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all - - feature_siem.host_isolation_all - - feature_siem.process_operations_all - - feature_siem.actions_log_management_all - - feature_siem.file_operations_all - - feature_siem.execute_operations_all - - feature_siem.scan_operations_all - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.policy_management_all + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all + - feature_siemV2.host_isolation_all + - feature_siemV2.process_operations_all + - feature_siemV2.actions_log_management_all + - feature_siemV2.file_operations_all + - feature_siemV2.execute_operations_all + - feature_siemV2.scan_operations_all + - feature_siemV2.workflow_insights_all - feature_securitySolutionCasesV2.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all @@ -769,19 +791,21 @@ endpoint_policy_manager: - application: 'kibana-.kibana' privileges: - feature_ml.all - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.policy_management_all - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all # Elastic Defend Policy Management - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.policy_management_all + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all # Elastic Defend Policy Management + - feature_siemV2.workflow_insights_all - feature_securitySolutionCasesV2.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all diff --git a/packages/kbn-es/src/serverless_resources/security_roles.json b/packages/kbn-es/src/serverless_resources/security_roles.json index 424cb898a4f96..6f85d0655dfb6 100644 --- a/packages/kbn-es/src/serverless_resources/security_roles.json +++ b/packages/kbn-es/src/serverless_resources/security_roles.json @@ -32,10 +32,12 @@ { "feature": { "ml": ["read"], - "siem": ["read", "read_alerts"], + "siemV2": ["read", "read_alerts"], "securitySolutionAssistant": ["all"], "securitySolutionAttackDiscovery": ["all"], "securitySolutionCasesV2": ["read"], + "securitySolutionTimeline": ["read"], + "securitySolutionNotes": ["read"], "actions": ["read"], "builtInAlerts": ["read"] }, @@ -79,10 +81,12 @@ { "feature": { "ml": ["read"], - "siem": ["read", "read_alerts"], + "siemV2": ["read", "read_alerts"], "securitySolutionAssistant": ["all"], "securitySolutionAttackDiscovery": ["all"], "securitySolutionCasesV2": ["read"], + "securitySolutionTimeline": ["read"], + "securitySolutionNotes": ["read"], "actions": ["read"], "builtInAlerts": ["read"] }, @@ -135,7 +139,7 @@ { "feature": { "ml": ["read"], - "siem": [ + "siemV2": [ "all", "read_alerts", "crud_alerts", @@ -153,6 +157,8 @@ "securitySolutionCasesV2": ["all"], "securitySolutionAssistant": ["all"], "securitySolutionAttackDiscovery": ["all"], + "securitySolutionTimeline": ["all"], + "securitySolutionNotes": ["all"], "actions": ["read"], "builtInAlerts": ["all"], "osquery": ["all"], @@ -207,10 +213,12 @@ { "feature": { "ml": ["read"], - "siem": ["all", "read_alerts", "crud_alerts"], + "siemV2": ["all", "read_alerts", "crud_alerts"], "securitySolutionAssistant": ["all"], "securitySolutionAttackDiscovery": ["all"], "securitySolutionCasesV2": ["all"], + "securitySolutionTimeline": ["all"], + "securitySolutionNotes": ["all"], "actions": ["read"], "builtInAlerts": ["all"] }, @@ -260,10 +268,12 @@ { "feature": { "ml": ["read"], - "siem": ["all", "read_alerts", "crud_alerts"], + "siemV2": ["all", "read_alerts", "crud_alerts"], "securitySolutionAssistant": ["all"], "securitySolutionAttackDiscovery": ["all"], "securitySolutionCasesV2": ["all"], + "securitySolutionTimeline": ["all"], + "securitySolutionNotes": ["all"], "actions": ["all"], "builtInAlerts": ["all"] }, @@ -308,10 +318,12 @@ { "feature": { "ml": ["all"], - "siem": ["all", "read_alerts", "crud_alerts"], + "siemV2": ["all", "read_alerts", "crud_alerts"], "securitySolutionAssistant": ["all"], "securitySolutionAttackDiscovery": ["all"], "securitySolutionCasesV2": ["all"], + "securitySolutionTimeline": ["all"], + "securitySolutionNotes": ["all"], "actions": ["read"], "builtInAlerts": ["all"], "dev_tools": ["all"] @@ -363,10 +375,12 @@ { "feature": { "ml": ["all"], - "siem": ["all", "read_alerts", "crud_alerts"], + "siemV2": ["all", "read_alerts", "crud_alerts"], "securitySolutionAssistant": ["all"], "securitySolutionAttackDiscovery": ["all"], "securitySolutionCasesV2": ["all"], + "securitySolutionTimeline": ["all"], + "securitySolutionNotes": ["all"], "actions": ["all"], "builtInAlerts": ["all"] }, diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 6f31687b36bac..c4f46400dc464 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -18,7 +18,7 @@ pageLoadAssetSize: cloudSecurityPosture: 34398 console: 61298 contentManagement: 16254 - controls: 60000 + controls: 12000 core: 564663 crossClusterReplication: 65408 customIntegrations: 22034 @@ -37,7 +37,7 @@ pageLoadAssetSize: discover: 99999 discoverEnhanced: 42730 discoverShared: 17111 - embeddable: 87309 + embeddable: 24000 embeddableEnhanced: 22107 enterpriseSearch: 66810 entityManager: 17175 @@ -123,7 +123,7 @@ pageLoadAssetSize: osquery: 107090 painlessLab: 179748 presentationPanel: 11468 - presentationUtil: 33186 + presentationUtil: 25000 productDocBase: 22500 profiling: 36694 remoteClusters: 51327 diff --git a/packages/kbn-relocate/constants.ts b/packages/kbn-relocate/constants.ts index b96db93cc4606..24f693c00e2f1 100644 --- a/packages/kbn-relocate/constants.ts +++ b/packages/kbn-relocate/constants.ts @@ -24,7 +24,7 @@ export const EXTENSIONS = [ 'lock', 'bazel', 'md', - 'mdz', + 'mdx', 'asciidoc', 'sh', 'snap', @@ -42,6 +42,10 @@ export const EXCLUDED_FOLDERS = [ './.es', './.git', // './.github', + './bazel-bin', + './bazel-kibana', + './bazel-out', + './bazel-testlogs', './.native_modules', './.node_binaries', './.vscode', @@ -56,6 +60,8 @@ export const EXCLUDED_FOLDERS = [ './trash', ]; +export const EXCLUDED_FOLDER_NAMES = ['target']; + export const NO_GREP = EXCLUDED_FOLDERS.map((f) => `--exclude-dir "${f}"`).join(' '); // These two constants are singletons, used and updated throughout the process diff --git a/packages/kbn-relocate/healthcheck.ts b/packages/kbn-relocate/healthcheck.ts new file mode 100644 index 0000000000000..5ebaf501cc701 --- /dev/null +++ b/packages/kbn-relocate/healthcheck.ts @@ -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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { ToolingLog } from '@kbn/tooling-log'; +import fs from 'fs'; +import path, { join } from 'path'; +import { getPackages } from '@kbn/repo-packages'; +import { REPO_ROOT } from '@kbn/repo-info'; +import { EXCLUDED_FOLDERS, EXCLUDED_FOLDER_NAMES, EXTENSIONS } from './constants'; +import { BASE_FOLDER } from './constants'; + +const findPaths = (content: string): string[] => { + const regex = /([\.]{1,2}(\/[^\s)\]\['`#"]+)+)/g; + return content.match(regex) || []; +}; + +const findUrls = (content: string): string[] => { + const regex = /http(s)?:\/\/([^\s)\]\['`#"]+)/g; + return content.match(regex) || []; +}; + +const checkUrlExists = async (url: string, tries = 3): Promise => { + try { + const response = await fetch(url, { method: 'GET' }); + return response.ok; + } catch (error) { + return tries > 0 ? checkUrlExists(url, tries - 1) : false; + } +}; + +const isModuleReference = (moduleNames: string[], reference: string): boolean => { + return ( + reference.includes('/packages/') || reference.includes('/plugins/') // || + // moduleNames.some((name) => reference.includes(name)) + ); +}; + +const checkIfResourceExists = (baseDir: string, reference: string): boolean => { + const filePath = join(baseDir, reference); + const rootReference = join(BASE_FOLDER, reference); + const fatherReference = join(baseDir, '..', reference); + + return ( + filePath.includes('/target') || // ignore target folders + filePath.includes('{') || // ignore paths with variables + filePath.includes('(') || // ignore paths with regexps / vars + filePath.includes('*') || // assume wildcard patterns exist + fs.existsSync(filePath) || + fs.existsSync(`${filePath}.ts`) || + fs.existsSync(`${filePath}.tsx`) || + fs.existsSync(`${filePath}.d.ts`) || + fs.existsSync(`${filePath}.js`) || + fs.existsSync(`${filePath}/index.ts`) || + fs.existsSync(`${filePath}/index.js`) || + fs.existsSync(rootReference) || + fs.existsSync(`${rootReference}.js`) || + fs.existsSync(fatherReference) + ); +}; + +const getAllFiles = ( + dirPath: string, + arrayOfFiles: fs.Dirent[] = [], + extensions?: string[] +): fs.Dirent[] => { + const files = fs.readdirSync(dirPath, { withFileTypes: true }); + + files.forEach((file) => { + const filePath = path.join(dirPath, file.name); + if ( + !EXCLUDED_FOLDERS.some((folder) => filePath.startsWith(join(BASE_FOLDER, folder))) && + !EXCLUDED_FOLDER_NAMES.includes(file.name) + ) { + if (fs.statSync(filePath).isDirectory()) { + arrayOfFiles = getAllFiles(filePath, arrayOfFiles); + } else { + if (!extensions || extensions.find((ext) => file.name.endsWith(ext))) { + arrayOfFiles.push(file); + } + } + } + }); + + return arrayOfFiles; +}; + +export const findBrokenReferences = async (log: ToolingLog) => { + const packages = getPackages(REPO_ROOT); + const moduleNames = packages.map((pkg) => pkg.directory.split('/').pop()!); + const files = getAllFiles(BASE_FOLDER, [], EXTENSIONS); + + for (const file of files) { + const fileBrokenReferences = []; + const filePath = join(file.path, file.name); + const content = fs.readFileSync(filePath, 'utf-8'); + const references = findPaths(content); + + for (const ref of references) { + if (isModuleReference(moduleNames, ref) && !checkIfResourceExists(file.path, ref)) { + fileBrokenReferences.push(ref); + } + } + + if (fileBrokenReferences.length > 0) { + log.info(filePath, fileBrokenReferences); + } + } +}; + +export const findBrokenLinks = async (log: ToolingLog) => { + const files = getAllFiles(BASE_FOLDER); + + for (const file of files) { + const fileBrokenLinks = []; + const filePath = join(file.path, file.name); + const content = fs.readFileSync(filePath, 'utf-8'); + const references = findUrls(content); + + for (const ref of references) { + if ( + ref.includes('github.com/elastic/kibana') && + ref.includes('blob') && + !(await checkUrlExists(ref)) + ) { + fileBrokenLinks.push(ref); + } + } + + if (fileBrokenLinks.length > 0) { + log.info(filePath, fileBrokenLinks); + } + } +}; diff --git a/packages/kbn-relocate/index.ts b/packages/kbn-relocate/index.ts index e2ffdb18adc37..78a8972adcc5e 100644 --- a/packages/kbn-relocate/index.ts +++ b/packages/kbn-relocate/index.ts @@ -10,6 +10,7 @@ import { run } from '@kbn/dev-cli-runner'; import { findAndRelocateModules, findAndMoveModule } from './relocate'; import { listModules } from './list'; +import { findBrokenLinks, findBrokenReferences } from './healthcheck'; const toStringArray = (flag: string | boolean | string[] | undefined): string[] => { if (typeof flag === 'string') { @@ -42,11 +43,19 @@ const toOptString = ( export const runKbnRelocateCli = () => { run( async ({ log, flags }) => { - if (typeof flags.moveOnly === 'string' && flags.moveOnly.length > 0) { + if (typeof flags.list === 'string' && flags.list.length > 0) { + await listModules(flags.list, log); + } else if (typeof flags.healthcheck === 'string' && flags.healthcheck.length > 0) { + if (flags.healthcheck === 'references') { + await findBrokenReferences(log); + } else if (flags.healthcheck === 'links') { + await findBrokenLinks(log); + } else { + log.error(`Unknown --healthcheck option: ${flags.healthcheck}`); + } + } else if (typeof flags.moveOnly === 'string' && flags.moveOnly.length > 0) { log.info('When using --moveOnly flag, the rest of flags are ignored.'); await findAndMoveModule(flags.moveOnly, log); - } else if (typeof flags.list === 'string' && flags.list.length > 0) { - await listModules(flags.list, log); } else { const { pr, team, path, include, exclude, baseBranch } = flags; await findAndRelocateModules( @@ -67,10 +76,25 @@ export const runKbnRelocateCli = () => { defaultLevel: 'info', }, flags: { - string: ['pr', 'team', 'path', 'include', 'exclude', 'baseBranch', 'moveOnly', 'list'], + string: [ + 'healthcheck', + 'pr', + 'team', + 'path', + 'include', + 'exclude', + 'baseBranch', + 'moveOnly', + 'list', + ], help: ` Usage: node scripts/relocate [options] + --list "all" List all Kibana modules + --list "uncategorised" List Kibana modules that are lacking 'group' or 'visibility' information + --list "incorrect" List Kibana modules that are not in the correct folder (aka folder does not match group/visibility in the manifest) + --healthcheck "references" Find broken references in Kibana codebase (Beta) + --healthcheck "links" Find broken links in Kibana codebase (Beta) --moveOnly Only move the specified module in the current branch (no cleanup, no branching, no commit) --pr Use the given PR number instead of creating a new one --team Include all modules (packages and plugins) belonging to the specified owner (can specify multiple teams) @@ -78,9 +102,6 @@ export const runKbnRelocateCli = () => { --include Include the specified module in the relocation (can specify multiple modules) --exclude Exclude the specified module from the relocation (can use multiple times) --baseBranch Use a branch different than 'main' (e.g. "8.x") - --list "all" List all Kibana modules - --list "uncategorised" List Kibana modules that are lacking 'group' or 'visibility' information - --list "incorrect" List Kibana modules that are not in the correct folder (aka folder does not match group/visibility in the manifest) E.g. relocate all modules owned by Core team and also modules owned by Operations team, excluding 'foo-module-id'. Force push into PR 239847: node scripts/relocate --pr 239847 --team @elastic/kibana-core --team @elastic/kibana-operations --exclude @kbn/foo-module-id diff --git a/packages/kbn-relocate/utils/transforms.ts b/packages/kbn-relocate/utils/transforms.ts index e3bd95b3a6c2d..023c36171e979 100644 --- a/packages/kbn-relocate/utils/transforms.ts +++ b/packages/kbn-relocate/utils/transforms.ts @@ -13,7 +13,10 @@ type TransformFunction = (param: string) => string; const TRANSFORMS: Record = { 'src/platform/packages/shared/chart_expressions/common': 'src/platform/packages/shared/chart-expressions-common', + 'x-pack/solutions/search/packages/search/shared_ui': 'x-pack/solutions/search/packages/shared_ui', 'x-pack/solutions/security/packages/security-solution/': 'x-pack/solutions/security/packages/', + 'x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant': + 'x-pack/platform/plugins/shared/observability_ai_assistant', 'x-pack/solutions/observability/plugins/observability_solution/': 'x-pack/solutions/observability/plugins/', 'x-pack/solutions/observability/packages/observability/observability_utils/observability_': diff --git a/packages/kbn-scout-reporting/src/helpers/index.ts b/packages/kbn-scout-reporting/src/helpers/index.ts index fc9442b2511a4..cb86e656086a6 100644 --- a/packages/kbn-scout-reporting/src/helpers/index.ts +++ b/packages/kbn-scout-reporting/src/helpers/index.ts @@ -8,6 +8,6 @@ */ export { getPluginManifestData, type PluginManifest } from './plugin_manifest'; -export { stripFilePath, parseStdout } from './text_processing'; +export { excapeHtmlCharacters, stripFilePath, parseStdout } from './text_processing'; export { getRunTarget, stripRunCommand } from './cli_processing'; export { getTestIDForTitle, generateTestRunId } from './test_id_generator'; diff --git a/packages/kbn-scout-reporting/src/helpers/text_processing.ts b/packages/kbn-scout-reporting/src/helpers/text_processing.ts index 6d7a7d394243e..14dc0a8c3c7e2 100644 --- a/packages/kbn-scout-reporting/src/helpers/text_processing.ts +++ b/packages/kbn-scout-reporting/src/helpers/text_processing.ts @@ -21,3 +21,6 @@ export function parseStdout(stdout: Array): string { // Escape special HTML characters return stripANSI(stdoutContent); } + +export const excapeHtmlCharacters = (htmlText: string): string => + htmlText.replace(/&/g, '&').replace(//g, '>'); diff --git a/packages/kbn-scout-reporting/src/reporting/playwright/failed_test/failed_test_reporter.ts b/packages/kbn-scout-reporting/src/reporting/playwright/failed_test/failed_test_reporter.ts index ec3fe1c757cda..944e1dc948e62 100644 --- a/packages/kbn-scout-reporting/src/reporting/playwright/failed_test/failed_test_reporter.ts +++ b/packages/kbn-scout-reporting/src/reporting/playwright/failed_test/failed_test_reporter.ts @@ -36,6 +36,7 @@ import { getTestIDForTitle, stripRunCommand, stripFilePath, + excapeHtmlCharacters, } from '../../../helpers'; /** @@ -105,7 +106,9 @@ export class ScoutFailedTestReporter implements Reporter { duration: result.duration, error: { message: result.error?.message ? stripFilePath(result.error.message) : undefined, - stack_trace: result.error?.stack ? stripFilePath(result.error.stack) : undefined, + stack_trace: result.error?.stack + ? excapeHtmlCharacters(stripFilePath(result.error.stack)) + : undefined, }, stdout: result.stdout ? parseStdout(result.stdout) : undefined, attachments: result.attachments.map((attachment) => ({ diff --git a/packages/kbn-test/src/jest/setup/enzyme.js b/packages/kbn-test/src/jest/setup/enzyme.js index d101358fd5b4a..aa4a629303bfa 100644 --- a/packages/kbn-test/src/jest/setup/enzyme.js +++ b/packages/kbn-test/src/jest/setup/enzyme.js @@ -11,3 +11,31 @@ import { configure } from 'enzyme'; import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; configure({ adapter: new Adapter() }); + +/* eslint-env jest */ + +/** + * This is a workaround to fix snapshot serialization of emotion classes when rendering React@18 using `import { render } from 'enzyme'` + * With React@18 emotion uses `useInsertionEffect` to insert styles into the DOM, which enzyme `render` does not trigger because it is using ReactDomServer.renderToString. + * With React@17 emotion fell back to sync cb, so it was working with enzyme `render`. + * Without those styles in DOM the custom snapshot serializer is not able to replace the emotion class names. + * This workaround ensures a fake emotion style tag is present in the DOM before rendering the component with enzyme making the snapshot serializer work. + */ +function mockEnsureEmotionStyleTag() { + if (!document.head.querySelector('style[data-emotion]')) { + const style = document.createElement('style'); + style.setAttribute('data-emotion', 'css'); + document.head.appendChild(style); + } +} + +jest.mock('enzyme', () => { + const actual = jest.requireActual('enzyme'); + return { + ...actual, + render: (node, options) => { + mockEnsureEmotionStyleTag(); + return actual.render(node, options); + }, + }; +}); diff --git a/packages/kbn-test/src/jest/setup/react_testing_library.js b/packages/kbn-test/src/jest/setup/react_testing_library.js index 7b184485df1cb..ce54bcf8326cb 100644 --- a/packages/kbn-test/src/jest/setup/react_testing_library.js +++ b/packages/kbn-test/src/jest/setup/react_testing_library.js @@ -80,6 +80,8 @@ console.error = (...args) => { * Tracking issue to clean this up https://github.com/elastic/kibana/issues/199100 */ if (REACT_VERSION.startsWith('18.')) { - console.warn('Running with React@18 and muting the legacy ReactDOM.render warning'); + if (!process.env.CI) { + console.warn('Running with React@18 and muting the legacy ReactDOM.render warning'); + } muteLegacyRootWarning(); } diff --git a/src/core/packages/http/router-server-internal/index.ts b/src/core/packages/http/router-server-internal/index.ts index f0cd26b1ba90b..1d3e01675850c 100644 --- a/src/core/packages/http/router-server-internal/index.ts +++ b/src/core/packages/http/router-server-internal/index.ts @@ -21,3 +21,4 @@ export { isKibanaRequest, isRealRequest, ensureRawRequest, CoreKibanaRequest } f export { isSafeMethod } from './src/route'; export { HapiResponseAdapter } from './src/response_adapter'; export { kibanaResponseFactory, lifecycleResponseFactory, KibanaResponse } from './src/response'; +export { getWarningHeaderMessageFromRouteDeprecation } from './src/get_warning_header_message'; diff --git a/src/core/packages/http/router-server-internal/src/get_warning_header_message.test.ts b/src/core/packages/http/router-server-internal/src/get_warning_header_message.test.ts new file mode 100644 index 0000000000000..a58907af4152a --- /dev/null +++ b/src/core/packages/http/router-server-internal/src/get_warning_header_message.test.ts @@ -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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { RouteDeprecationInfo } from '@kbn/core-http-server'; +import { getWarningHeaderMessageFromRouteDeprecation } from './get_warning_header_message'; + +describe('getWarningHeaderMessageFromRouteDeprecation', () => { + it('creates the warning with a default message if the deprecation object does not have one', () => { + const kibanaVersion = '12.31.45'; + const expectedMessage = `299 Kibana-${kibanaVersion} "This endpoint deprecated"`; + const deprecationObject: RouteDeprecationInfo = { + reason: { type: 'deprecate' }, + severity: 'warning', + documentationUrl: 'fakeurl.com', + }; + expect(getWarningHeaderMessageFromRouteDeprecation(deprecationObject, expectedMessage)).toMatch( + expectedMessage + ); + }); + + it('creates the warning with the deprecation object message', () => { + const kibanaVersion = '12.31.45'; + const msg = 'Custom deprecation message for this object'; + const expectedMessage = `299 Kibana-${kibanaVersion} "${msg}"`; + const deprecationObject: RouteDeprecationInfo = { + reason: { type: 'deprecate' }, + severity: 'warning', + documentationUrl: 'fakeurl.com', + message: msg, + }; + expect(getWarningHeaderMessageFromRouteDeprecation(deprecationObject, expectedMessage)).toMatch( + expectedMessage + ); + }); +}); diff --git a/src/core/packages/http/router-server-internal/src/get_warning_header_message.ts b/src/core/packages/http/router-server-internal/src/get_warning_header_message.ts new file mode 100644 index 0000000000000..bc69a4d5c0ccb --- /dev/null +++ b/src/core/packages/http/router-server-internal/src/get_warning_header_message.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { RouteDeprecationInfo } from '@kbn/core-http-server'; + +export function getWarningHeaderMessageFromRouteDeprecation( + deprecationObject: RouteDeprecationInfo, + kibanaVersion: string +): string { + const msg = deprecationObject.message ?? 'This endpoint is deprecated'; + const warningMessage = `299 Kibana-${kibanaVersion} "${msg}"`; + return warningMessage; +} diff --git a/src/core/packages/http/router-server-internal/src/router.test.ts b/src/core/packages/http/router-server-internal/src/router.test.ts index ee1b3d234b71f..54e5e11c6252c 100644 --- a/src/core/packages/http/router-server-internal/src/router.test.ts +++ b/src/core/packages/http/router-server-internal/src/router.test.ts @@ -14,6 +14,7 @@ import { createRequestMock } from '@kbn/hapi-mocks/src/request'; import { createFooValidation } from './router.test.util'; import { Router, type RouterOptions } from './router'; import type { RouteValidatorRequestAndResponses } from '@kbn/core-http-server'; +import { getEnvOptions, createTestEnv } from '@kbn/config-mocks'; const mockResponse = { code: jest.fn().mockImplementation(() => mockResponse), @@ -26,9 +27,12 @@ const mockResponseToolkit = { const logger = loggingSystemMock.create().get(); const enhanceWithContext = (fn: (...args: any[]) => any) => fn.bind(null, {}); +const options = getEnvOptions(); +options.cliArgs.dev = false; +const env = createTestEnv({ envOptions: options }); const routerOptions: RouterOptions = { - isDev: false, + env, versionedRouterOptions: { defaultHandlerResolutionStrategy: 'oldest', useVersionResolutionStrategyForInternalPaths: [], @@ -273,7 +277,7 @@ describe('Router', () => { it('registers pluginId if provided', () => { const pluginId = Symbol('test'); - const router = new Router('', logger, enhanceWithContext, { pluginId }); + const router = new Router('', logger, enhanceWithContext, { pluginId, env }); expect(router.pluginId).toBe(pluginId); }); diff --git a/src/core/packages/http/router-server-internal/src/router.ts b/src/core/packages/http/router-server-internal/src/router.ts index fcf70341b0c41..df1675a03b6a8 100644 --- a/src/core/packages/http/router-server-internal/src/router.ts +++ b/src/core/packages/http/router-server-internal/src/router.ts @@ -30,6 +30,7 @@ import type { IKibanaResponse, } from '@kbn/core-http-server'; import type { RouteSecurityGetter } from '@kbn/core-http-server'; +import { Env } from '@kbn/config'; import { CoreVersionedRouter } from './versioned_router'; import { CoreKibanaRequest, getProtocolFromRequest } from './request'; import { kibanaResponseFactory } from './response'; @@ -72,8 +73,7 @@ export type InternalRouterRoute = Omit & { /** @internal */ export interface RouterOptions { - /** Whether we are running in development */ - isDev?: boolean; + env: Env; /** Plugin for which this router was registered */ pluginId?: symbol; @@ -203,7 +203,7 @@ export class Router { let router: Router; @@ -33,6 +39,7 @@ describe('Versioned route', () => { versionedRouter = CoreVersionedRouter.from({ router, log: loggingSystemMock.createLogger(), + env: notDevEnv, }); }); @@ -198,7 +205,7 @@ describe('Versioned route', () => { it('allows public versions other than "2023-10-31"', () => { expect(() => - CoreVersionedRouter.from({ router, log: loggingSystemMock.createLogger(), isDev: false }) + CoreVersionedRouter.from({ router, log: loggingSystemMock.createLogger(), env: notDevEnv }) .get({ access: 'public', path: '/foo' }) .addVersion({ version: '2023-01-31', validate: false }, (ctx, req, res) => res.ok()) ).not.toThrow(); @@ -297,7 +304,7 @@ describe('Versioned route', () => { beforeEach(() => { versionedRouter = CoreVersionedRouter.from({ router, - isDev: true, + env: devEnv, log: loggingSystemMock.createLogger(), }); }); @@ -346,7 +353,7 @@ describe('Versioned route', () => { (router.registerRoute as jest.Mock).mockImplementation((opts) => (handler = opts.handler)); versionedRouter = CoreVersionedRouter.from({ router, - isDev: true, + env: devEnv, log: loggingSystemMock.createLogger(), }); versionedRouter.post({ path: '/test/{id}', access: 'internal' }).addVersion( @@ -379,7 +386,7 @@ describe('Versioned route', () => { (router.registerRoute as jest.Mock).mockImplementation((opts) => (handler = opts.handler)); versionedRouter = CoreVersionedRouter.from({ router, - isDev: true, + env: devEnv, log: loggingSystemMock.createLogger(), }); versionedRouter.post({ path: '/test/{id}', access: 'internal' }).addVersion( @@ -411,7 +418,7 @@ describe('Versioned route', () => { it('allows using default resolution for specific internal routes', async () => { versionedRouter = CoreVersionedRouter.from({ router, - isDev: true, + env: devEnv, log: loggingSystemMock.createLogger(), useVersionResolutionStrategyForInternalPaths: ['/bypass_me/{id?}'], }); diff --git a/src/core/packages/http/router-server-internal/src/versioned_router/core_versioned_route.ts b/src/core/packages/http/router-server-internal/src/versioned_router/core_versioned_route.ts index 04560c3e76e5a..a1243fd8c4b0a 100644 --- a/src/core/packages/http/router-server-internal/src/versioned_router/core_versioned_route.ts +++ b/src/core/packages/http/router-server-internal/src/versioned_router/core_versioned_route.ts @@ -25,6 +25,7 @@ import type { } from '@kbn/core-http-server'; import { Request } from '@hapi/hapi'; import { Logger } from '@kbn/logging'; +import { Env } from '@kbn/config'; import type { HandlerResolutionStrategy, Method, Options } from './types'; import { @@ -34,7 +35,7 @@ import { readVersion, removeQueryVersion, } from './route_version_utils'; -import { injectVersionHeader } from '../util'; +import { injectResponseHeaders, injectVersionHeader } from '../util'; import { validRouteSecurity } from '../security_route_config_validator'; import { resolvers } from './handler_resolvers'; @@ -44,9 +45,10 @@ import { RequestHandlerEnhanced, Router } from '../router'; import { kibanaResponseFactory as responseFactory } from '../response'; import { validateHapiRequest } from '../route'; import { RouteValidator } from '../validator'; +import { getWarningHeaderMessageFromRouteDeprecation } from '../get_warning_header_message'; interface InternalVersionedRouteConfig extends VersionedRouteConfig { - isDev: boolean; + env: Env; useVersionResolutionStrategyForInternalPaths: Map; defaultHandlerResolutionStrategy: HandlerResolutionStrategy; } @@ -86,7 +88,7 @@ export class CoreVersionedRoute implements VersionedRoute { private useDefaultStrategyForPath: boolean; private isPublic: boolean; - private isDev: boolean; + private env: Env; private enableQueryVersion: boolean; private defaultSecurityConfig: RouteSecurity | undefined; private defaultHandlerResolutionStrategy: HandlerResolutionStrategy; @@ -98,13 +100,13 @@ export class CoreVersionedRoute implements VersionedRoute { internalOptions: InternalVersionedRouteConfig ) { const { - isDev, + env, useVersionResolutionStrategyForInternalPaths, defaultHandlerResolutionStrategy, ...options } = internalOptions; this.isPublic = options.access === 'public'; - this.isDev = isDev; + this.env = env; this.defaultHandlerResolutionStrategy = defaultHandlerResolutionStrategy; this.useDefaultStrategyForPath = this.isPublic || useVersionResolutionStrategyForInternalPaths.has(path); @@ -146,7 +148,7 @@ export class CoreVersionedRoute implements VersionedRoute { if (!maybeVersion) { if (this.useDefaultStrategyForPath) { version = this.getDefaultVersion(); - } else if (!this.isDev && !this.isPublic) { + } else if (!this.env.mode.dev && !this.isPublic) { // When in production, we default internal routes to v1 to allow // gracefully onboarding of un-versioned to versioned routes version = '1'; @@ -211,9 +213,22 @@ export class CoreVersionedRoute implements VersionedRoute { return injectVersionHeader(version, error); } - const response = await handler.fn(kibanaRequest, responseFactory); + let response = await handler.fn(kibanaRequest, responseFactory); - if (this.isDev && validation?.response?.[response.status]?.body) { + // we don't want to overwrite the header value + if (handler.options.options?.deprecated && !response.options.headers?.warning) { + response = injectResponseHeaders( + { + warning: getWarningHeaderMessageFromRouteDeprecation( + handler.options.options.deprecated, + this.env.packageInfo.version + ), + }, + response + ); + } + + if (this.env.mode.dev && validation?.response?.[response.status]?.body) { const { [response.status]: responseValidation, unsafe } = validation.response; try { const validator = RouteValidator.from({ @@ -235,7 +250,7 @@ export class CoreVersionedRoute implements VersionedRoute { private validateVersion(version: string) { // We do an additional check here while we only have a single allowed public version // for all public Kibana HTTP APIs - if (this.isDev && this.isPublic) { + if (this.env.mode.dev && this.isPublic) { const message = isAllowedPublicVersion(version); if (message) { throw new Error(message); diff --git a/src/core/packages/http/router-server-internal/src/versioned_router/core_versioned_router.test.ts b/src/core/packages/http/router-server-internal/src/versioned_router/core_versioned_router.test.ts index 7b9fbbf938807..bba25a4a9799a 100644 --- a/src/core/packages/http/router-server-internal/src/versioned_router/core_versioned_router.test.ts +++ b/src/core/packages/http/router-server-internal/src/versioned_router/core_versioned_router.test.ts @@ -11,6 +11,7 @@ import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import { Router } from '../router'; import { CoreVersionedRouter } from '.'; import { createRouter } from './mocks'; +import { createTestEnv } from '@kbn/config-mocks'; const pluginId = Symbol('test'); describe('Versioned router', () => { @@ -21,6 +22,7 @@ describe('Versioned router', () => { versionedRouter = CoreVersionedRouter.from({ router, log: loggingSystemMock.createLogger(), + env: createTestEnv(), }); }); diff --git a/src/core/packages/http/router-server-internal/src/versioned_router/core_versioned_router.ts b/src/core/packages/http/router-server-internal/src/versioned_router/core_versioned_router.ts index 0570ac3cf099c..16b5b60e9598c 100644 --- a/src/core/packages/http/router-server-internal/src/versioned_router/core_versioned_router.ts +++ b/src/core/packages/http/router-server-internal/src/versioned_router/core_versioned_router.ts @@ -15,6 +15,7 @@ import type { } from '@kbn/core-http-server'; import { omit } from 'lodash'; import { Logger } from '@kbn/logging'; +import { Env } from '@kbn/config'; import { CoreVersionedRoute } from './core_versioned_route'; import type { HandlerResolutionStrategy, Method } from './types'; import type { Router } from '../router'; @@ -30,7 +31,7 @@ export interface VersionedRouterArgs { */ defaultHandlerResolutionStrategy?: HandlerResolutionStrategy; /** Whether Kibana is running in a dev environment */ - isDev?: boolean; + env: Env; /** * List of internal paths that should use the default handler resolution strategy. By default this * is no routes ([]) because ONLY Elastic clients are intended to call internal routes. @@ -57,14 +58,14 @@ export class CoreVersionedRouter implements VersionedRouter { router, log, defaultHandlerResolutionStrategy, - isDev, + env, useVersionResolutionStrategyForInternalPaths, }: VersionedRouterArgs) { return new CoreVersionedRouter( router, log, defaultHandlerResolutionStrategy, - isDev, + env, useVersionResolutionStrategyForInternalPaths ); } @@ -72,7 +73,7 @@ export class CoreVersionedRouter implements VersionedRouter { public readonly router: Router, private readonly log: Logger, public readonly defaultHandlerResolutionStrategy: HandlerResolutionStrategy = 'oldest', - public readonly isDev: boolean = false, + public readonly env: Env, useVersionResolutionStrategyForInternalPaths: string[] = [] ) { this.pluginId = this.router.pluginId; @@ -94,7 +95,7 @@ export class CoreVersionedRouter implements VersionedRouter { defaultHandlerResolutionStrategy: this.defaultHandlerResolutionStrategy, useVersionResolutionStrategyForInternalPaths: this.useVersionResolutionStrategyForInternalPaths, - isDev: this.isDev, + env: this.env, }, }); this.routes.add(route); diff --git a/src/core/packages/http/router-server-internal/tsconfig.json b/src/core/packages/http/router-server-internal/tsconfig.json index 7887583e6e462..15bac8a66e445 100644 --- a/src/core/packages/http/router-server-internal/tsconfig.json +++ b/src/core/packages/http/router-server-internal/tsconfig.json @@ -19,7 +19,9 @@ "@kbn/core-logging-server-mocks", "@kbn/logging", "@kbn/core-http-common", - "@kbn/logging-mocks" + "@kbn/logging-mocks", + "@kbn/config-mocks", + "@kbn/config" ], "exclude": [ "target/**/*", diff --git a/src/core/packages/http/server-internal/src/http_server.test.ts b/src/core/packages/http/server-internal/src/http_server.test.ts index 72a94177233be..9b5c1c392935b 100644 --- a/src/core/packages/http/server-internal/src/http_server.test.ts +++ b/src/core/packages/http/server-internal/src/http_server.test.ts @@ -32,9 +32,14 @@ import { KBN_CERT_PATH, KBN_KEY_PATH } from '@kbn/dev-utils'; import moment from 'moment'; import { of, Observable, BehaviorSubject } from 'rxjs'; import { mockCoreContext } from '@kbn/core-base-server-mocks'; +import { createTestEnv, getEnvOptions } from '@kbn/config-mocks'; + +const options = getEnvOptions(); +options.cliArgs.dev = false; +const env = createTestEnv({ envOptions: options }); const routerOptions: RouterOptions = { - isDev: false, + env, versionedRouterOptions: { defaultHandlerResolutionStrategy: 'oldest', useVersionResolutionStrategyForInternalPaths: [], diff --git a/src/core/packages/http/server-internal/src/http_service.test.ts b/src/core/packages/http/server-internal/src/http_service.test.ts index 9740cb0233355..e2aa841ffad32 100644 --- a/src/core/packages/http/server-internal/src/http_service.test.ts +++ b/src/core/packages/http/server-internal/src/http_service.test.ts @@ -486,7 +486,7 @@ test('passes versioned config to router', async () => { expect.any(Object), // logger expect.any(Function), // context enhancer expect.objectContaining({ - isDev: true, + env, versionedRouterOptions: { defaultHandlerResolutionStrategy: 'newest', useVersionResolutionStrategyForInternalPaths: ['/foo'], diff --git a/src/core/packages/http/server-internal/src/http_service.ts b/src/core/packages/http/server-internal/src/http_service.ts index 4b3f3a37f494b..5d43a7a203882 100644 --- a/src/core/packages/http/server-internal/src/http_service.ts +++ b/src/core/packages/http/server-internal/src/http_service.ts @@ -147,7 +147,7 @@ export class HttpService this.log, prebootServerRequestHandlerContext.createHandler.bind(null, this.coreContext.coreId), { - isDev: this.env.mode.dev, + env: this.env, versionedRouterOptions: getVersionedRouterOptions(config), } ); @@ -196,7 +196,7 @@ export class HttpService ) => { const enhanceHandler = this.requestHandlerContext!.createHandler.bind(null, pluginId); const router = new Router(path, this.log, enhanceHandler, { - isDev: this.env.mode.dev, + env: this.env, versionedRouterOptions: getVersionedRouterOptions(config), pluginId, }); diff --git a/src/core/packages/http/server-internal/src/lifecycle/on_pre_response.ts b/src/core/packages/http/server-internal/src/lifecycle/on_pre_response.ts index 7f489e4bb5f77..f8cafcf313667 100644 --- a/src/core/packages/http/server-internal/src/lifecycle/on_pre_response.ts +++ b/src/core/packages/http/server-internal/src/lifecycle/on_pre_response.ts @@ -66,11 +66,13 @@ export function adoptToHapiOnPreResponseFormat(fn: OnPreResponseHandler, log: Lo try { if (response) { - const statusCode: number = isBoom(response) + const isResponseBoom = isBoom(response); + const statusCode: number = isResponseBoom ? response.output.statusCode : response.statusCode; + const headers: ResponseHeaders = isResponseBoom ? {} : response.headers; - const result = await fn(CoreKibanaRequest.from(request), { statusCode }, toolkit); + const result = await fn(CoreKibanaRequest.from(request), { statusCode, headers }, toolkit); if (preResponseResult.isNext(result)) { if (result.headers) { diff --git a/src/core/packages/http/server-internal/src/lifecycle_handlers.test.ts b/src/core/packages/http/server-internal/src/lifecycle_handlers.test.ts index 28f8c70ebbb1e..b86b48379cf6c 100644 --- a/src/core/packages/http/server-internal/src/lifecycle_handlers.test.ts +++ b/src/core/packages/http/server-internal/src/lifecycle_handlers.test.ts @@ -22,6 +22,7 @@ import { INTERNAL_API_RESTRICTED_LOGGER_NAME, createBuildNrMismatchLoggerPreResponseHandler, createCustomHeadersPreResponseHandler, + createDeprecationWarningHeaderPreResponseHandler, createRestrictInternalRoutesPostAuthHandler, createVersionCheckPostAuthHandler, createXsrfPostAuthHandler, @@ -547,6 +548,50 @@ describe('customHeaders pre-response handler', () => { }); }); +describe('deprecation header pre-response handler', () => { + let toolkit: ToolkitMock; + + beforeEach(() => { + toolkit = createToolkit(); + }); + + it('adds the deprecation warning header to the request going to a deprecated route', () => { + const kibanaVersion = '19.73.41'; + const deprecationMessage = 'This is a deprecated endpoint message in the tests'; + const warningHeader = `299 Kibana-${kibanaVersion} "${deprecationMessage}"`; + const handler = createDeprecationWarningHeaderPreResponseHandler(kibanaVersion); + + handler( + { route: { options: { deprecated: { message: deprecationMessage } } } } as any, + {} as any, + toolkit + ); + + expect(toolkit.next).toHaveBeenCalledTimes(1); + expect(toolkit.next).toHaveBeenCalledWith({ + headers: { + warning: warningHeader, + }, + }); + }); + + it('does not add the deprecation warning header to the request going to a non-deprecated route', () => { + const kibanaVersion = '19.73.41'; + const deprecationMessage = 'This is a deprecated endpoint message in the tests'; + const warningHeader = `299 Kibana-${kibanaVersion} "${deprecationMessage}"`; + const handler = createDeprecationWarningHeaderPreResponseHandler(kibanaVersion); + + handler({ route: { options: { deprecated: {} } } } as any, {} as any, toolkit); + + expect(toolkit.next).toHaveBeenCalledTimes(1); + expect(toolkit.next).not.toHaveBeenCalledWith({ + headers: { + warning: warningHeader, + }, + }); + }); +}); + describe('build number mismatch logger on error pre-response handler', () => { let logger: jest.Mocked; diff --git a/src/core/packages/http/server-internal/src/lifecycle_handlers.ts b/src/core/packages/http/server-internal/src/lifecycle_handlers.ts index c460559fcec52..1bd1466b4c3bf 100644 --- a/src/core/packages/http/server-internal/src/lifecycle_handlers.ts +++ b/src/core/packages/http/server-internal/src/lifecycle_handlers.ts @@ -13,7 +13,10 @@ import type { OnPreResponseInfo, KibanaRequest, } from '@kbn/core-http-server'; -import { isSafeMethod } from '@kbn/core-http-router-server-internal'; +import { + getWarningHeaderMessageFromRouteDeprecation, + isSafeMethod, +} from '@kbn/core-http-router-server-internal'; import { Logger } from '@kbn/logging'; import { KIBANA_BUILD_NR_HEADER } from '@kbn/core-http-common'; import { HttpConfig } from './http_config'; @@ -120,6 +123,24 @@ export const createCustomHeadersPreResponseHandler = (config: HttpConfig): OnPre }; }; +export const createDeprecationWarningHeaderPreResponseHandler = ( + kibanaVersion: string +): OnPreResponseHandler => { + return (request, response, toolkit) => { + // we don't want to overwrite the header value + if (!request.route.options.deprecated || response.headers?.warning) { + return toolkit.next(); + } + const additionalHeaders = { + warning: getWarningHeaderMessageFromRouteDeprecation( + request.route.options.deprecated, + kibanaVersion + ), + }; + return toolkit.next({ headers: { ...additionalHeaders } }); + }; +}; + const shouldLogBuildNumberMismatch = ( serverBuild: { number: number; string: string }, request: KibanaRequest, diff --git a/src/core/packages/http/server-internal/src/register_lifecycle_handlers.ts b/src/core/packages/http/server-internal/src/register_lifecycle_handlers.ts index f11810f9afc3c..a504bb418843b 100644 --- a/src/core/packages/http/server-internal/src/register_lifecycle_handlers.ts +++ b/src/core/packages/http/server-internal/src/register_lifecycle_handlers.ts @@ -17,6 +17,7 @@ import { createVersionCheckPostAuthHandler, createBuildNrMismatchLoggerPreResponseHandler, createXsrfPostAuthHandler, + createDeprecationWarningHeaderPreResponseHandler, } from './lifecycle_handlers'; export const registerCoreHandlers = ( @@ -27,6 +28,10 @@ export const registerCoreHandlers = ( ) => { // add headers based on config registrar.registerOnPreResponse(createCustomHeadersPreResponseHandler(config)); + // add headers for deprecated endpoints + registrar.registerOnPreResponse( + createDeprecationWarningHeaderPreResponseHandler(env.packageInfo.version) + ); // add extra request checks stuff registrar.registerOnPostAuth(createXsrfPostAuthHandler(config)); if (config.versioned.strictClientVersionCheck !== false) { diff --git a/src/core/packages/http/server/src/lifecycle/on_pre_response.ts b/src/core/packages/http/server/src/lifecycle/on_pre_response.ts index 8ca5e91aaa502..79cd5e24719f3 100644 --- a/src/core/packages/http/server/src/lifecycle/on_pre_response.ts +++ b/src/core/packages/http/server/src/lifecycle/on_pre_response.ts @@ -65,6 +65,8 @@ export interface OnPreResponseExtensions { */ export interface OnPreResponseInfo { statusCode: number; + /** So any pre response handler can check the headers if needed, to avoid an overwrite for example */ + headers?: ResponseHeaders; } /** diff --git a/src/core/packages/http/server/src/router/route.ts b/src/core/packages/http/server/src/router/route.ts index c8d0683234dc7..adce8aae39e39 100644 --- a/src/core/packages/http/server/src/router/route.ts +++ b/src/core/packages/http/server/src/router/route.ts @@ -128,6 +128,8 @@ export interface RouteDeprecationInfo { documentationUrl: string; /** * The description message to be displayed for the deprecation. + * This will also appear in the '299 Kibana-{version} {message}' header warning when someone calls the route. + * Keep the message concise to avoid long header values. It is recommended to keep the message under 255 characters. * Check the README for writing deprecations in `src/core/server/deprecations/README.mdx` */ message?: string; diff --git a/src/core/packages/injected-metadata/common-internal/src/types.ts b/src/core/packages/injected-metadata/common-internal/src/types.ts index e988420720900..ce88073ca7bac 100644 --- a/src/core/packages/injected-metadata/common-internal/src/types.ts +++ b/src/core/packages/injected-metadata/common-internal/src/types.ts @@ -11,7 +11,7 @@ import type { PluginName, DiscoveredPlugin } from '@kbn/core-base-common'; import type { ThemeVersion } from '@kbn/ui-shared-deps-npm'; import type { EnvironmentMode, PackageInfo } from '@kbn/config'; import type { CustomBranding } from '@kbn/core-custom-branding-common'; -import type { DarkModeValue } from '@kbn/core-ui-settings-common'; +import type { DarkModeValue, ThemeName } from '@kbn/core-ui-settings-common'; import type { BrowserLoggingConfig } from '@kbn/core-logging-common-internal'; /** @internal */ @@ -41,7 +41,7 @@ export interface InjectedMetadataExternalUrlPolicy { /** @internal */ export interface InjectedMetadataTheme { darkMode: DarkModeValue; - name: string; + name: ThemeName; version: ThemeVersion; stylesheetPaths: { default: string[]; diff --git a/src/core/packages/overlays/browser-internal/src/modal/__snapshots__/modal_service.test.tsx.snap b/src/core/packages/overlays/browser-internal/src/modal/__snapshots__/modal_service.test.tsx.snap index d3e0381a65383..9717c0fea96c0 100644 --- a/src/core/packages/overlays/browser-internal/src/modal/__snapshots__/modal_service.test.tsx.snap +++ b/src/core/packages/overlays/browser-internal/src/modal/__snapshots__/modal_service.test.tsx.snap @@ -111,7 +111,7 @@ Array [ "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, ], @@ -423,14 +423,14 @@ Array [ "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, Object { "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, ], @@ -812,21 +812,21 @@ Array [ "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, Object { "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, Object { "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, ], @@ -1126,21 +1126,21 @@ Array [ "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, Object { "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, Object { "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, ], @@ -1445,21 +1445,21 @@ Array [ "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, Object { "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, Object { "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, ], @@ -1753,21 +1753,21 @@ Array [ "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, Object { "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, Object { "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, ], @@ -2002,7 +2002,7 @@ Array [ "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, ], @@ -2142,7 +2142,7 @@ Array [ "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, ], @@ -2287,7 +2287,7 @@ Array [ "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, ], @@ -2421,7 +2421,7 @@ Array [ "type": "return", "value": Object { "darkMode": false, - "name": "amsterdam", + "name": "borealis", }, }, ], diff --git a/src/core/packages/rendering/server-internal/src/bootstrap/bootstrap_renderer.test.ts b/src/core/packages/rendering/server-internal/src/bootstrap/bootstrap_renderer.test.ts index 7c1bbfc85c29f..8576d075c1fbc 100644 --- a/src/core/packages/rendering/server-internal/src/bootstrap/bootstrap_renderer.test.ts +++ b/src/core/packages/rendering/server-internal/src/bootstrap/bootstrap_renderer.test.ts @@ -35,13 +35,13 @@ const createPackageInfo = (parts: Partial = {}): PackageInfo => ({ }); const getClientGetMockImplementation = - ({ darkMode, name }: { darkMode?: boolean; name?: string } = {}) => + ({ darkMode, name }: { darkMode?: boolean | string; name?: string } = {}) => (key: string) => { switch (key) { case 'theme:darkMode': return Promise.resolve(darkMode ?? false); case 'theme:name': - return Promise.resolve(name ?? 'amsterdam'); + return Promise.resolve(name ?? 'borealis'); } return Promise.resolve(); }; @@ -67,7 +67,7 @@ describe('bootstrapRenderer', () => { packageInfo = createPackageInfo(); userSettingsService = userSettingsServiceMock.createSetupContract(); - getThemeTagMock.mockReturnValue('v8light'); + getThemeTagMock.mockReturnValue('borealislight'); getPluginsBundlePathsMock.mockReturnValue(new Map()); renderTemplateMock.mockReturnValue('__rendered__'); getJsDependencyPathsMock.mockReturnValue([]); @@ -124,7 +124,7 @@ describe('bootstrapRenderer', () => { expect(getThemeTagMock).toHaveBeenCalledTimes(1); expect(getThemeTagMock).toHaveBeenCalledWith({ - name: 'v8', + name: 'borealis', darkMode: true, }); }); @@ -141,7 +141,7 @@ describe('bootstrapRenderer', () => { expect(getThemeTagMock).toHaveBeenCalledTimes(1); expect(getThemeTagMock).toHaveBeenCalledWith({ - name: 'v8', + name: 'borealis', darkMode: false, }); }); @@ -167,7 +167,7 @@ describe('bootstrapRenderer', () => { expect(getThemeTagMock).toHaveBeenCalledTimes(1); expect(getThemeTagMock).toHaveBeenCalledWith({ - name: 'v8', + name: 'borealis', darkMode: true, }); }); @@ -192,7 +192,7 @@ describe('bootstrapRenderer', () => { expect(getThemeTagMock).toHaveBeenCalledTimes(1); expect(getThemeTagMock).toHaveBeenCalledWith({ - name: 'v8', + name: 'borealis', darkMode: false, }); }); @@ -217,7 +217,7 @@ describe('bootstrapRenderer', () => { expect(getThemeTagMock).toHaveBeenCalledTimes(1); expect(getThemeTagMock).toHaveBeenCalledWith({ - name: 'v8', + name: 'borealis', darkMode: false, }); }); @@ -247,7 +247,7 @@ describe('bootstrapRenderer', () => { expect(getThemeTagMock).toHaveBeenCalledTimes(1); expect(getThemeTagMock).toHaveBeenCalledWith({ - name: 'v8', + name: 'borealis', darkMode: true, }); }); @@ -290,13 +290,17 @@ describe('bootstrapRenderer', () => { expect(getThemeTagMock).toHaveBeenCalledTimes(1); expect(getThemeTagMock).toHaveBeenCalledWith({ - name: 'v8', + name: 'borealis', darkMode: true, }); }); it('calls getThemeTag with the correct parameters when darkMode is `system`', async () => { - uiSettingsClient.get.mockResolvedValue('system'); + uiSettingsClient.get.mockImplementation( + getClientGetMockImplementation({ + darkMode: 'system', + }) + ); const request = httpServerMock.createKibanaRequest(); @@ -307,7 +311,7 @@ describe('bootstrapRenderer', () => { expect(getThemeTagMock).toHaveBeenCalledTimes(1); expect(getThemeTagMock).toHaveBeenCalledWith({ - name: 'system', + name: 'borealis', darkMode: false, }); }); @@ -321,7 +325,7 @@ describe('bootstrapRenderer', () => { }); }); - it('does not call uiSettingsClient.get', async () => { + it('does not call uiSettingsClient.get with `theme:darkMode`', async () => { const request = httpServerMock.createKibanaRequest(); await renderer({ @@ -329,7 +333,7 @@ describe('bootstrapRenderer', () => { uiSettingsClient, }); - expect(uiSettingsClient.get).not.toHaveBeenCalled(); + expect(uiSettingsClient.get).not.toHaveBeenCalledWith('theme:darkMode'); }); it('calls getThemeTag with the default parameters', async () => { @@ -367,7 +371,7 @@ describe('bootstrapRenderer', () => { expect(getThemeTagMock).toHaveBeenCalledTimes(1); expect(getThemeTagMock).toHaveBeenCalledWith({ - name: 'v8', + name: 'borealis', darkMode: false, }); }); diff --git a/src/core/packages/rendering/server-internal/src/bootstrap/bootstrap_renderer.ts b/src/core/packages/rendering/server-internal/src/bootstrap/bootstrap_renderer.ts index f861f97922204..5b1cfc7c0c368 100644 --- a/src/core/packages/rendering/server-internal/src/bootstrap/bootstrap_renderer.ts +++ b/src/core/packages/rendering/server-internal/src/bootstrap/bootstrap_renderer.ts @@ -12,8 +12,10 @@ import { PackageInfo } from '@kbn/config'; import type { KibanaRequest, HttpAuth } from '@kbn/core-http-server'; import { type DarkModeValue, + type ThemeName, DEFAULT_THEME_NAME, parseDarkModeValue, + parseThemeNameValue, } from '@kbn/core-ui-settings-common'; import type { IUiSettingsClient } from '@kbn/core-ui-settings-server'; import type { UiPlugins } from '@kbn/core-plugins-base-server-internal'; @@ -62,13 +64,11 @@ export const bootstrapRendererFactory: BootstrapRendererFactory = ({ return async function bootstrapRenderer({ uiSettingsClient, request, isAnonymousPage = false }) { let darkMode: DarkModeValue = false; - let themeName: string = DEFAULT_THEME_NAME; - - if (packageInfo.buildFlavor !== 'serverless') { - themeName = 'borealis'; - } + let themeName: ThemeName = DEFAULT_THEME_NAME; try { + themeName = parseThemeNameValue(await uiSettingsClient.get('theme:name')); + const authenticated = isAuthenticated(request); if (authenticated) { @@ -79,8 +79,6 @@ export const bootstrapRendererFactory: BootstrapRendererFactory = ({ } else { darkMode = parseDarkModeValue(await uiSettingsClient.get('theme:darkMode')); } - - themeName = await uiSettingsClient.get('theme:name'); } } catch (e) { // just use the default values in case of connectivity issues with ES diff --git a/src/core/packages/rendering/server-internal/src/rendering_service.tsx b/src/core/packages/rendering/server-internal/src/rendering_service.tsx index a92c3dac485b5..babf533e51dba 100644 --- a/src/core/packages/rendering/server-internal/src/rendering_service.tsx +++ b/src/core/packages/rendering/server-internal/src/rendering_service.tsx @@ -21,6 +21,7 @@ import type { UiPlugins } from '@kbn/core-plugins-base-server-internal'; import type { CustomBranding } from '@kbn/core-custom-branding-common'; import { type DarkModeValue, + type ThemeName, parseDarkModeValue, parseThemeNameValue, type UiSettingsParams, @@ -212,7 +213,7 @@ export class RenderingService { darkMode = getSettingValue('theme:darkMode', settings, parseDarkModeValue); } - const themeName = getSettingValue('theme:name', settings, parseThemeNameValue); + const themeName = getSettingValue('theme:name', settings, parseThemeNameValue); const themeStylesheetPaths = (mode: boolean) => getThemeStylesheetPaths({ diff --git a/src/core/packages/ui-settings/common/src/theme.ts b/src/core/packages/ui-settings/common/src/theme.ts index 6c95531cddc38..33d613e19ad56 100644 --- a/src/core/packages/ui-settings/common/src/theme.ts +++ b/src/core/packages/ui-settings/common/src/theme.ts @@ -7,8 +7,8 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -export const DEFAULT_THEME_NAME = 'amsterdam'; -export const SUPPORTED_THEME_NAMES = ['amsterdam', 'borealis']; +export const DEFAULT_THEME_NAME = 'borealis'; +export const SUPPORTED_THEME_NAMES = ['amsterdam', 'borealis'] as const; export type ThemeName = (typeof SUPPORTED_THEME_NAMES)[number]; @@ -37,7 +37,7 @@ export type ThemeTags = readonly ThemeTag[]; */ export const DEFAULT_THEME_TAGS: ThemeTags = SUPPORTED_THEME_TAGS; -export const FALLBACK_THEME_TAG: ThemeTag = 'v8light'; +export const FALLBACK_THEME_TAG: ThemeTag = 'borealislight'; const isValidTag = (tag: unknown) => SUPPORTED_THEME_TAGS.includes(tag as (typeof SUPPORTED_THEME_TAGS)[number]); diff --git a/src/core/packages/ui-settings/server-internal/src/settings/index.test.ts b/src/core/packages/ui-settings/server-internal/src/settings/index.test.ts index b4e30e7c3599d..bc0c1a2a47710 100644 --- a/src/core/packages/ui-settings/server-internal/src/settings/index.test.ts +++ b/src/core/packages/ui-settings/server-internal/src/settings/index.test.ts @@ -17,7 +17,6 @@ import { getStateSettings } from './state'; import { getAnnouncementsSettings } from './announcements'; const defaultOptions: GetCoreSettingsOptions = { - isServerless: false, isDist: true, isThemeSwitcherEnabled: undefined, }; diff --git a/src/core/packages/ui-settings/server-internal/src/settings/index.ts b/src/core/packages/ui-settings/server-internal/src/settings/index.ts index a9ea940605bd1..5e348d2aec097 100644 --- a/src/core/packages/ui-settings/server-internal/src/settings/index.ts +++ b/src/core/packages/ui-settings/server-internal/src/settings/index.ts @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import type { UiSettingsParams } from '@kbn/core-ui-settings-common'; +import type { ThemeName, UiSettingsParams } from '@kbn/core-ui-settings-common'; import { getAccessibilitySettings } from './accessibility'; import { getDateFormatSettings } from './date_formats'; import { getMiscUiSettings } from './misc'; @@ -17,9 +17,9 @@ import { getStateSettings } from './state'; import { getAnnouncementsSettings } from './announcements'; export interface GetCoreSettingsOptions { - isServerless: boolean; isDist: boolean; isThemeSwitcherEnabled: boolean | undefined; + defaultTheme?: ThemeName; } export const getCoreSettings = ( diff --git a/src/core/packages/ui-settings/server-internal/src/settings/theme.test.ts b/src/core/packages/ui-settings/server-internal/src/settings/theme.test.ts index 45d6f48f9d535..c18a11fda10db 100644 --- a/src/core/packages/ui-settings/server-internal/src/settings/theme.test.ts +++ b/src/core/packages/ui-settings/server-internal/src/settings/theme.test.ts @@ -11,7 +11,6 @@ import type { UiSettingsParams } from '@kbn/core-ui-settings-common'; import { getThemeSettings, type GetThemeSettingsOptions } from './theme'; const defaultOptions: GetThemeSettingsOptions = { - isServerless: false, isDist: true, isThemeSwitcherEnabled: undefined, }; @@ -42,6 +41,8 @@ describe('theme settings', () => { const validate = getValidationFn(themeSettings['theme:name']); it('should only accept expected values', () => { + // TODO: Remove amsterdam theme + // https://github.com/elastic/eui-private/issues/170 expect(() => validate('amsterdam')).not.toThrow(); expect(() => validate('borealis')).not.toThrow(); @@ -50,25 +51,24 @@ describe('theme settings', () => { }); describe('readonly', () => { - it('should be readonly when `isServerless = true`', () => { + it('should not be editable when `isThemeSwitcherEnabled` is falsy', () => { + expect(getThemeSettings(defaultOptions)['theme:name'].readonly).toBe(true); expect( - getThemeSettings({ ...defaultOptions, isServerless: true })['theme:name'].readonly + getThemeSettings({ + ...defaultOptions, + isThemeSwitcherEnabled: false, + })['theme:name'].readonly ).toBe(true); - expect( - getThemeSettings({ ...defaultOptions, isServerless: false })['theme:name'].readonly - ).toBe(false); }); it('should be editable when `isThemeSwitcherEnabled = true`', () => { expect( - getThemeSettings({ ...defaultOptions, isServerless: true, isThemeSwitcherEnabled: true })[ - 'theme:name' - ].readonly + getThemeSettings({ ...defaultOptions, isThemeSwitcherEnabled: true })['theme:name'] + .readonly ).toBe(false); expect( getThemeSettings({ ...defaultOptions, - isServerless: false, isThemeSwitcherEnabled: true, })['theme:name'].readonly ).toBe(false); @@ -76,16 +76,17 @@ describe('theme settings', () => { }); describe('value', () => { - it('should default to `amsterdam` when `isServerless = true`', () => { - expect( - getThemeSettings({ ...defaultOptions, isServerless: true })['theme:name'].value - ).toBe('amsterdam'); + it('should default to `borealis`', () => { + expect(getThemeSettings(defaultOptions)['theme:name'].value).toBe('borealis'); }); - it('should default to `borealis` when `isServerless = false`', () => { + it('should use the `defaultTheme` value when defined', () => { expect( - getThemeSettings({ ...defaultOptions, isServerless: false })['theme:name'].value - ).toBe('borealis'); + getThemeSettings({ + ...defaultOptions, + defaultTheme: 'amsterdam', + })['theme:name'].value + ).toBe('amsterdam'); }); }); }); diff --git a/src/core/packages/ui-settings/server-internal/src/settings/theme.ts b/src/core/packages/ui-settings/server-internal/src/settings/theme.ts index ef8b3df843ea9..87551111bf91c 100644 --- a/src/core/packages/ui-settings/server-internal/src/settings/theme.ts +++ b/src/core/packages/ui-settings/server-internal/src/settings/theme.ts @@ -9,6 +9,7 @@ import { schema } from '@kbn/config-schema'; import { i18n } from '@kbn/i18n'; +import type { Writable } from '@kbn/utility-types'; import type { ThemeVersion } from '@kbn/ui-shared-deps-npm'; import { type UiSettingsParams, @@ -17,18 +18,17 @@ import { SUPPORTED_THEME_NAMES, DEFAULT_THEME_NAME, } from '@kbn/core-ui-settings-common'; +import { defaultThemeSchema } from '../ui_settings_config'; interface ThemeInfo { defaultDarkMode: boolean; - defaultThemeName: ThemeName; } -const getThemeInfo = ({ isDist, isServerless }: GetThemeSettingsOptions): ThemeInfo => { +const getThemeInfo = ({ isDist }: GetThemeSettingsOptions): ThemeInfo => { const themeTags = parseThemeTags(process.env.KBN_OPTIMIZER_THEMES); const themeInfo: ThemeInfo = { defaultDarkMode: false, - defaultThemeName: DEFAULT_THEME_NAME, }; if (!isDist) { @@ -36,30 +36,20 @@ const getThemeInfo = ({ isDist, isServerless }: GetThemeSettingsOptions): ThemeI themeInfo.defaultDarkMode = themeTags[0]?.endsWith('dark') || false; } - if (!isServerless) { - // Default to Borealis theme in non-serverless - themeInfo.defaultThemeName = 'borealis'; - } - return themeInfo; }; export interface GetThemeSettingsOptions { - isServerless: boolean; isDist: boolean; isThemeSwitcherEnabled: boolean | undefined; + defaultTheme?: ThemeName; } export const getThemeSettings = ( options: GetThemeSettingsOptions ): Record => { - const { defaultDarkMode, defaultThemeName } = getThemeInfo(options); - - // Make `theme:name` readonly in serverless unless the theme switcher is enabled - let isThemeNameReadonly = options.isServerless; - if (options.isThemeSwitcherEnabled !== undefined) { - isThemeNameReadonly = !options.isThemeSwitcherEnabled; - } + const { defaultDarkMode } = getThemeInfo(options); + const defaultTheme = options.defaultTheme ?? DEFAULT_THEME_NAME; return { 'theme:darkMode': { @@ -122,7 +112,8 @@ export const getThemeSettings = ( defaultMessage: 'Theme', }), type: 'select', - options: SUPPORTED_THEME_NAMES, + // Cast to a mutable array to satisfy the `UiSettingsParams.options` type + options: SUPPORTED_THEME_NAMES as Writable, optionLabels: { amsterdam: i18n.translate('core.ui_settings.params.themeName.options.amsterdam', { defaultMessage: 'Amsterdam', @@ -131,15 +122,10 @@ export const getThemeSettings = ( defaultMessage: 'Borealis', }), }, - value: defaultThemeName, - readonly: isThemeNameReadonly, + value: defaultTheme, + readonly: !options.isThemeSwitcherEnabled, requiresPageReload: true, - schema: schema.oneOf([ - schema.literal('amsterdam'), - schema.literal('borealis'), - // Allow experimental themes - schema.string(), - ]), + schema: defaultThemeSchema, }, }; }; diff --git a/src/core/packages/ui-settings/server-internal/src/ui_settings_config.ts b/src/core/packages/ui-settings/server-internal/src/ui_settings_config.ts index 04b7ff6b0f558..1dd1cd8273892 100644 --- a/src/core/packages/ui-settings/server-internal/src/ui_settings_config.ts +++ b/src/core/packages/ui-settings/server-internal/src/ui_settings_config.ts @@ -9,6 +9,7 @@ import { schema, TypeOf, offeringBasedSchema } from '@kbn/config-schema'; import type { ServiceConfigDescriptor } from '@kbn/core-base-server-internal'; +import { DEFAULT_THEME_NAME } from '@kbn/core-ui-settings-common'; import { ConfigDeprecationProvider } from '@kbn/config'; const deprecations: ConfigDeprecationProvider = ({ unused, renameFromRoot }) => [ @@ -16,12 +17,22 @@ const deprecations: ConfigDeprecationProvider = ({ unused, renameFromRoot }) => renameFromRoot('server.defaultRoute', 'uiSettings.overrides.defaultRoute', { level: 'warning' }), ]; +export const defaultThemeSchema = schema.oneOf([ + // TODO: Remove amsterdam theme + // https://github.com/elastic/eui-private/issues/170 + schema.literal('amsterdam'), + schema.literal('borealis'), + // Allow experimental themes + schema.string(), +]); + const configSchema = schema.object({ overrides: schema.object({}, { unknowns: 'allow' }), publicApiEnabled: offeringBasedSchema({ serverless: schema.boolean({ defaultValue: false }) }), experimental: schema.maybe( schema.object({ themeSwitcherEnabled: schema.maybe(schema.boolean({ defaultValue: false })), + defaultTheme: schema.maybe(schema.string({ defaultValue: DEFAULT_THEME_NAME })), }) ), }); diff --git a/src/core/packages/ui-settings/server-internal/src/ui_settings_service.ts b/src/core/packages/ui-settings/server-internal/src/ui_settings_service.ts index 83e968761776f..ba2ccdab5e626 100644 --- a/src/core/packages/ui-settings/server-internal/src/ui_settings_service.ts +++ b/src/core/packages/ui-settings/server-internal/src/ui_settings_service.ts @@ -18,6 +18,7 @@ import type { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-ser import type { InternalSavedObjectsServiceSetup } from '@kbn/core-saved-objects-server-internal'; import type { ReadonlyModeType, + ThemeName, UiSettingsParams, UiSettingsScope, } from '@kbn/core-ui-settings-common'; @@ -53,7 +54,6 @@ export class UiSettingsService private readonly config$: Observable; private readonly isDist: boolean; private readonly isDev: boolean; - private readonly isServerless: boolean; private readonly uiSettingsDefaults = new Map(); private readonly uiSettingsGlobalDefaults = new Map(); private overrides: Record = {}; @@ -64,7 +64,6 @@ export class UiSettingsService this.isDist = coreContext.env.packageInfo.dist; this.config$ = coreContext.configService.atPath(uiConfigDefinition.path); this.isDev = coreContext.env.mode.dev; - this.isServerless = coreContext.env.packageInfo.buildFlavor === 'serverless'; } public async preboot(): Promise { @@ -76,8 +75,8 @@ export class UiSettingsService this.register( getCoreSettings({ isDist: this.isDist, - isServerless: this.isServerless, isThemeSwitcherEnabled: experimental?.themeSwitcherEnabled, + defaultTheme: experimental?.defaultTheme as ThemeName, }) ); diff --git a/src/core/packages/ui-settings/server-internal/tsconfig.json b/src/core/packages/ui-settings/server-internal/tsconfig.json index 09887438dda56..f0e81686a2c78 100644 --- a/src/core/packages/ui-settings/server-internal/tsconfig.json +++ b/src/core/packages/ui-settings/server-internal/tsconfig.json @@ -32,6 +32,7 @@ "@kbn/core-logging-server-mocks", "@kbn/core-saved-objects-api-server-internal", "@kbn/core-saved-objects-common", + "@kbn/utility-types", ], "exclude": [ "target/**/*", diff --git a/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts b/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts index 353ef8c85548d..43d5403245e64 100644 --- a/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts +++ b/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts @@ -105,7 +105,7 @@ describe('checking migration metadata changes on all registered SO types', () => "file": "6b65ae5899b60ebe08656fd163ea532e557d3c98", "file-upload-usage-collection-telemetry": "06e0a8c04f991e744e09d03ab2bd7f86b2088200", "fileShare": "5be52de1747d249a221b5241af2838264e19aaa1", - "fleet-agent-policies": "908765a33aab066f4ac09446686b2d884aceed00", + "fleet-agent-policies": "4a5c6477d2a61121e95ea9865ed1403a28c38706", "fleet-fleet-server-host": "69be15f6b6f2a2875ad3c7050ddea7a87f505417", "fleet-message-signing-keys": "93421f43fed2526b59092a4e3c65d64bc2266c0f", "fleet-package-policies": "0206c20f27286787b91814a2e7872f06dc1e8e47", @@ -121,7 +121,7 @@ describe('checking migration metadata changes on all registered SO types', () => "infra-custom-dashboards": "1a5994f2e05bb8a1609825ddbf5012f77c5c67f3", "infrastructure-monitoring-log-view": "5f86709d3c27aed7a8379153b08ee5d3d90d77f5", "infrastructure-ui-source": "113182d6895764378dfe7fa9fa027244f3a457c4", - "ingest-agent-policies": "c1818c4119259908875b4c777ae62b11ba0585cd", + "ingest-agent-policies": "57ebfb047cf0b81c6fa0ceed8586fa7199c7c5e2", "ingest-download-sources": "279a68147e62e4d8858c09ad1cf03bd5551ce58d", "ingest-outputs": "55988d5f778bbe0e76caa7e6468707a0a056bdd8", "ingest-package-policies": "60d43f475f91417d14d9df05476acf2e63e99435", diff --git a/src/core/server/integration_tests/http/http2_protocol.test.ts b/src/core/server/integration_tests/http/http2_protocol.test.ts index 8f22a7a144c5e..5c519ec61ad93 100644 --- a/src/core/server/integration_tests/http/http2_protocol.test.ts +++ b/src/core/server/integration_tests/http/http2_protocol.test.ts @@ -22,6 +22,11 @@ import { } from '@kbn/core-http-server-internal'; import { mockCoreContext } from '@kbn/core-base-server-mocks'; import type { Logger } from '@kbn/logging'; +import { createTestEnv, getEnvOptions } from '@kbn/config-mocks'; + +const options = getEnvOptions(); +options.cliArgs.dev = false; +const env = createTestEnv({ envOptions: options }); const CSP_CONFIG = cspConfig.schema.validate({}); const EXTERNAL_URL_CONFIG = externalUrlConfig.schema.validate({}); @@ -74,7 +79,7 @@ describe('Http2 - Smoke tests', () => { innerServerListener = innerServer.listener; const router = new Router('', logger, enhanceWithContext, { - isDev: false, + env, versionedRouterOptions: { defaultHandlerResolutionStrategy: 'oldest', }, @@ -177,7 +182,7 @@ describe('Http2 - Smoke tests', () => { innerServerListener = innerServer.listener; const router = new Router('', logger, enhanceWithContext, { - isDev: false, + env, versionedRouterOptions: { defaultHandlerResolutionStrategy: 'oldest', }, diff --git a/src/core/server/integration_tests/http/http_server.test.ts b/src/core/server/integration_tests/http/http_server.test.ts index 5e17cbbc94972..295932890fec3 100644 --- a/src/core/server/integration_tests/http/http_server.test.ts +++ b/src/core/server/integration_tests/http/http_server.test.ts @@ -16,6 +16,11 @@ import { Router } from '@kbn/core-http-router-server-internal'; import { HttpServer, HttpConfig } from '@kbn/core-http-server-internal'; import { mockCoreContext } from '@kbn/core-base-server-mocks'; import type { Logger } from '@kbn/logging'; +import { createTestEnv, getEnvOptions } from '@kbn/config-mocks'; + +const options = getEnvOptions(); +options.cliArgs.dev = false; +const env = createTestEnv({ envOptions: options }); describe('Http server', () => { let server: HttpServer; @@ -60,7 +65,7 @@ describe('Http server', () => { innerServerListener = innerServer.listener; const router = new Router('', logger, enhanceWithContext, { - isDev: false, + env, versionedRouterOptions: { defaultHandlerResolutionStrategy: 'oldest', }, diff --git a/src/core/server/integration_tests/http/lifecycle.test.ts b/src/core/server/integration_tests/http/lifecycle.test.ts index 1063f00e48edf..b97107ade0da5 100644 --- a/src/core/server/integration_tests/http/lifecycle.test.ts +++ b/src/core/server/integration_tests/http/lifecycle.test.ts @@ -16,6 +16,9 @@ import { contextServiceMock } from '@kbn/core-http-context-server-mocks'; import { ensureRawRequest } from '@kbn/core-http-router-server-internal'; import { HttpService } from '@kbn/core-http-server-internal'; import { createHttpService } from '@kbn/core-http-server-mocks'; +import { Env } from '@kbn/config'; +import { REPO_ROOT } from '@kbn/repo-info'; +import { getEnvOptions } from '@kbn/config-mocks'; let server: HttpService; @@ -28,6 +31,8 @@ const setupDeps = { executionContext: executionContextServiceMock.createInternalSetupContract(), }; +const kibanaVersion = Env.createDefault(REPO_ROOT, getEnvOptions()).packageInfo.version; + beforeEach(async () => { logger = loggingSystemMock.create(); server = createHttpService({ logger }); @@ -1503,6 +1508,195 @@ describe('runs with default preResponse handlers', () => { }); }); +describe('runs with default preResponse deprecation handlers', () => { + const deprecationMessage = 'This is a deprecated endpoint for testing reasons'; + const warningString = `299 Kibana-${kibanaVersion} "${deprecationMessage}"`; + + it('should handle a deprecated route and include deprecation warning headers', async () => { + const { server: innerServer, createRouter } = await server.setup(setupDeps); + const router = createRouter('/'); + + router.get( + { + path: '/deprecated', + validate: false, + options: { + deprecated: { + documentationUrl: 'https://fake-url.com', + reason: { type: 'deprecate' }, + severity: 'warning', + message: deprecationMessage, + }, + }, + }, + (context, req, res) => res.ok({}) + ); + + await server.start(); + + const response = await supertest(innerServer.listener).get('/deprecated').expect(200); + + expect(response.header.warning).toMatch(warningString); + }); + + it('should not add a deprecation warning header to a non deprecated route', async () => { + const { server: innerServer, createRouter } = await server.setup(setupDeps); + const router = createRouter('/'); + + router.get( + { + path: '/test', + validate: false, + }, + (context, req, res) => res.ok({}) + ); + + await server.start(); + + const response = await supertest(innerServer.listener).get('/test').expect(200); + + expect(response.header.warning).toBeUndefined(); + }); + + it('should not overwrite the warning header if it was already set', async () => { + const { server: innerServer, createRouter } = await server.setup(setupDeps); + const router = createRouter('/'); + const expectedWarningHeader = 'This should not get overwritten'; + + router.get( + { + path: '/deprecated', + validate: false, + options: { + deprecated: { + documentationUrl: 'https://fake-url.com', + reason: { type: 'deprecate' }, + severity: 'warning', + message: deprecationMessage, + }, + }, + }, + (context, req, res) => res.ok({ headers: { warning: expectedWarningHeader } }) + ); + + await server.start(); + + const response = await supertest(innerServer.listener).get('/deprecated').expect(200); + expect(response.header.warning).toMatch(expectedWarningHeader); + }); + + it('should return the warning header in deprecated v1 but not in non deprecated v2', async () => { + const { server: innerServer, createRouter } = await server.setup(setupDeps); + const router = createRouter('/'); + + router.versioned + .get({ + access: 'internal', + path: '/test', + }) + .addVersion( + { + version: '1', + validate: false, + options: { + deprecated: { + documentationUrl: 'https://fake-url.com', + reason: { type: 'deprecate' }, + severity: 'warning', + message: deprecationMessage, + }, + }, + }, + async (ctx, req, res) => { + return res.ok({ body: { v: '1' } }); + } + ) + .addVersion( + { + version: '2', + validate: false, + }, + async (ctx, req, res) => { + return res.ok({ body: { v: '2' } }); + } + ); + + await server.start(); + + let response = await supertest(innerServer.listener) + .get('/test') + .set('Elastic-Api-Version', '1') + .expect(200); + + expect(response.body.v).toMatch('1'); + expect(response.header.warning).toMatch(warningString); + + response = await supertest(innerServer.listener) + .get('/test') + .set('Elastic-Api-Version', '2') + .expect(200); + + expect(response.body.v).toMatch('2'); + expect(response.header.warning).toBeUndefined(); + }); + + it('should not overwrite the warning header if it was already set (versioned)', async () => { + const { server: innerServer, createRouter } = await server.setup(setupDeps); + const router = createRouter('/'); + const expectedWarningHeader = 'This should not get overwritten'; + + router.versioned + .get({ + access: 'internal', + path: '/test', + }) + .addVersion( + { + version: '1', + validate: false, + options: { + deprecated: { + documentationUrl: 'https://fake-url.com', + reason: { type: 'deprecate' }, + severity: 'warning', + message: deprecationMessage, + }, + }, + }, + async (ctx, req, res) => { + return res.ok({ body: { v: '1' }, headers: { warning: expectedWarningHeader } }); + } + ) + .addVersion( + { + version: '2', + validate: false, + }, + async (ctx, req, res) => { + return res.ok({ body: { v: '2' } }); + } + ); + + await server.start(); + + let response = await supertest(innerServer.listener) + .get('/test') + .set('Elastic-Api-Version', '1') + .expect(200); + + expect(response.body.v).toMatch('1'); + expect(response.header.warning).toMatch(expectedWarningHeader); + + response = await supertest(innerServer.listener) + .get('/test') + .set('Elastic-Api-Version', '2') + .expect(200); + + expect(response.body.v).toMatch('2'); + expect(response.header.warning).toBeUndefined(); + }); +}); + describe('run interceptors in the right order', () => { it('with Auth registered', async () => { const { diff --git a/src/core/server/integration_tests/http/router.test.ts b/src/core/server/integration_tests/http/router.test.ts index c0a690e479e67..b8fadbb34216c 100644 --- a/src/core/server/integration_tests/http/router.test.ts +++ b/src/core/server/integration_tests/http/router.test.ts @@ -22,6 +22,11 @@ import { Router } from '@kbn/core-http-router-server-internal'; import { createHttpService } from '@kbn/core-http-server-mocks'; import type { HttpService } from '@kbn/core-http-server-internal'; import { loggerMock } from '@kbn/logging-mocks'; +import { createTestEnv, getEnvOptions } from '@kbn/config-mocks'; + +const options = getEnvOptions(); +options.cliArgs.dev = false; +const env = createTestEnv({ envOptions: options }); let server: HttpService; let logger: ReturnType; @@ -2266,7 +2271,7 @@ describe('registerRouterAfterListening', () => { const enhanceWithContext = (fn: (...args: any[]) => any) => fn.bind(null, {}); const otherRouter = new Router('/test', loggerMock.create(), enhanceWithContext, { - isDev: false, + env, versionedRouterOptions: { defaultHandlerResolutionStrategy: 'oldest', }, @@ -2303,7 +2308,7 @@ describe('registerRouterAfterListening', () => { const enhanceWithContext = (fn: (...args: any[]) => any) => fn.bind(null, {}); const otherRouter = new Router('/test', loggerMock.create(), enhanceWithContext, { - isDev: false, + env, versionedRouterOptions: { defaultHandlerResolutionStrategy: 'oldest', }, diff --git a/src/core/server/integration_tests/http/tls_config_reload.test.ts b/src/core/server/integration_tests/http/tls_config_reload.test.ts index c19e92361af39..205c6580d1459 100644 --- a/src/core/server/integration_tests/http/tls_config_reload.test.ts +++ b/src/core/server/integration_tests/http/tls_config_reload.test.ts @@ -23,6 +23,11 @@ import { import { isServerTLS, flattenCertificateChain, fetchPeerCertificate } from './tls_utils'; import { mockCoreContext } from '@kbn/core-base-server-mocks'; import type { Logger } from '@kbn/logging'; +import { createTestEnv, getEnvOptions } from '@kbn/config-mocks'; + +const options = getEnvOptions(); +options.cliArgs.dev = false; +const env = createTestEnv({ envOptions: options }); const CSP_CONFIG = cspConfig.schema.validate({}); const EXTERNAL_URL_CONFIG = externalUrlConfig.schema.validate({}); @@ -70,7 +75,7 @@ describe('HttpServer - TLS config', () => { const listener = innerServer.listener; const router = new Router('', logger, enhanceWithContext, { - isDev: false, + env, versionedRouterOptions: { defaultHandlerResolutionStrategy: 'oldest', }, diff --git a/src/dev/build/tasks/os_packages/docker_generator/run.ts b/src/dev/build/tasks/os_packages/docker_generator/run.ts index ce2c39f5bd457..6bbd280a4bf11 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/run.ts +++ b/src/dev/build/tasks/os_packages/docker_generator/run.ts @@ -51,7 +51,7 @@ export async function runDockerGenerator( */ if (flags.baseImage === 'wolfi') baseImageName = - 'docker.elastic.co/wolfi/chainguard-base:latest@sha256:dd66beec64a7f9b19c6c35a1195153b2b630a55e16ec71949ed5187c5947eea1'; + 'docker.elastic.co/wolfi/chainguard-base:latest@sha256:ea157dd3d70787c6b6dc9e14dda1ff103c781d4c3f9a544393ff4583dd80c9d0'; let imageFlavor = ''; if (flags.baseImage === 'ubi') imageFlavor += `-ubi`; diff --git a/src/dev/storybook/aliases.ts b/src/dev/storybook/aliases.ts index 7fffaf223266c..e3df535fb9988 100644 --- a/src/dev/storybook/aliases.ts +++ b/src/dev/storybook/aliases.ts @@ -67,8 +67,9 @@ export const storybookAliases = { presentation: 'src/platform/plugins/shared/presentation_util/storybook', random_sampling: 'x-pack/platform/packages/private/kbn-random-sampling/.storybook', esql_editor: 'src/platform/packages/private/kbn-esql-editor/.storybook', - security_solution: 'x-pack/solutions/security/plugins/security_solution/.storybook', - security_solution_packages: 'x-pack/solutions/security/packages/storybook/config', + // Skipped, please check and fix https://github.com/elastic/kibana/issues/207227 + // security_solution: 'x-pack/solutions/security/plugins/security_solution/.storybook', + // security_solution_packages: 'x-pack/solutions/security/packages/storybook/config', serverless: 'packages/serverless/storybook/config', shared_ux: 'src/platform/packages/private/shared-ux/storybook/config', threat_intelligence: 'x-pack/solutions/security/plugins/threat_intelligence/.storybook', diff --git a/src/platform/packages/private/kbn-esql-editor/src/editor_footer/history_starred_queries.test.tsx b/src/platform/packages/private/kbn-esql-editor/src/editor_footer/history_starred_queries.test.tsx index ba00e7eae6359..98c0977437fb1 100644 --- a/src/platform/packages/private/kbn-esql-editor/src/editor_footer/history_starred_queries.test.tsx +++ b/src/platform/packages/private/kbn-esql-editor/src/editor_footer/history_starred_queries.test.tsx @@ -78,6 +78,7 @@ describe('Starred and History queries components', () => { field: 'queryString', name: 'Query', render: expect.anything(), + css: expect.anything(), }, { 'data-test-subj': 'timeRan', @@ -120,6 +121,7 @@ describe('Starred and History queries components', () => { field: 'queryString', name: 'Query', render: expect.anything(), + css: expect.anything(), }, { 'data-test-subj': 'timeRan', @@ -171,6 +173,7 @@ describe('Starred and History queries components', () => { field: 'queryString', name: 'Query', render: expect.anything(), + css: expect.anything(), }, { actions: [], diff --git a/src/platform/packages/private/kbn-esql-editor/src/editor_footer/history_starred_queries.tsx b/src/platform/packages/private/kbn-esql-editor/src/editor_footer/history_starred_queries.tsx index 069cd74eb83da..e129c1a1d8b54 100644 --- a/src/platform/packages/private/kbn-esql-editor/src/editor_footer/history_starred_queries.tsx +++ b/src/platform/packages/private/kbn-esql-editor/src/editor_footer/history_starred_queries.tsx @@ -194,6 +194,11 @@ export const getTableColumns = ( name: i18n.translate('esqlEditor.query.recentQueriesColumnLabel', { defaultMessage: 'Query', }), + css: css` + .euiTableCellContent { + align-items: flex-start; + } + `, render: (queryString: QueryHistoryItem['queryString']) => ( { if (containerRef.current) { const textIsOverlapping = containerRef.current.offsetWidth < containerRef.current.scrollWidth; - setIsExpandable(textIsOverlapping); + setIsExpandable(textIsOverlapping || isRowExpanded); } - }, [containerWidth]); + }, [containerWidth, isRowExpanded, queryString]); return ( <> diff --git a/src/platform/packages/private/kbn-generate-csv/src/generate_csv_esql.test.ts b/src/platform/packages/private/kbn-generate-csv/src/generate_csv_esql.test.ts index d2ee8e8345438..8dbcfba7bbc9d 100644 --- a/src/platform/packages/private/kbn-generate-csv/src/generate_csv_esql.test.ts +++ b/src/platform/packages/private/kbn-generate-csv/src/generate_csv_esql.test.ts @@ -32,11 +32,8 @@ import { } from '../constants'; import { CsvESQLGenerator, JobParamsCsvESQL } from './generate_csv_esql'; -const createMockJob = ( - params: Partial = { query: { esql: '' } } -): JobParamsCsvESQL => ({ +const createMockJob = (params: JobParamsCsvESQL): JobParamsCsvESQL => ({ ...params, - query: { esql: '' }, }); const mockTaskInstanceFields = { startedAt: null, retryAt: null }; @@ -106,7 +103,7 @@ describe('CsvESQLGenerator', () => { it('formats an empty search result to CSV content', async () => { const generateCsv = new CsvESQLGenerator( - createMockJob({ columns: ['date', 'ip', 'message'] }), + createMockJob({ query: { esql: '' }, columns: ['date', 'ip', 'message'] }), mockConfig, mockTaskInstanceFields, { @@ -138,7 +135,7 @@ describe('CsvESQLGenerator', () => { }); const generateCsv = new CsvESQLGenerator( - createMockJob(), + createMockJob({ query: { esql: '' } }), mockConfig, mockTaskInstanceFields, { @@ -166,7 +163,7 @@ describe('CsvESQLGenerator', () => { }); const generateCsv = new CsvESQLGenerator( - createMockJob(), + createMockJob({ query: { esql: '' } }), mockConfig, mockTaskInstanceFields, { @@ -196,7 +193,7 @@ describe('CsvESQLGenerator', () => { }); const generateCsv = new CsvESQLGenerator( - createMockJob(), + createMockJob({ query: { esql: '' } }), mockConfig, mockTaskInstanceFields, { @@ -286,7 +283,7 @@ describe('CsvESQLGenerator', () => { }); const generateCsvPromise = new CsvESQLGenerator( - createMockJob(), + createMockJob({ query: { esql: '' } }), mockConfigWithAutoScrollDuration, taskInstanceFields, { @@ -362,7 +359,7 @@ describe('CsvESQLGenerator', () => { }); const generateCsvPromise = new CsvESQLGenerator( - createMockJob(), + createMockJob({ query: { esql: '' } }), mockConfigWithAutoScrollDuration, taskInstanceFields, { @@ -413,7 +410,7 @@ describe('CsvESQLGenerator', () => { }); const generateCsv = new CsvESQLGenerator( - createMockJob({ columns: ['message', 'date', 'something else'] }), + createMockJob({ query: { esql: '' }, columns: ['message', 'date', 'something else'] }), mockConfig, mockTaskInstanceFields, { @@ -484,7 +481,80 @@ describe('CsvESQLGenerator', () => { }, }, locale: 'en', - query: '', + query: query.esql, + }, + }, + { + strategy: 'esql', + transport: { + requestTimeout: '30s', + }, + abortSignal: expect.any(AbortSignal), + } + ); + }); + + it('passes params to the query', async () => { + const query = { + esql: 'FROM custom-metrics-without-timestamp | WHERE event.ingested >= ?_tstart AND event.ingested <= ?_tend', + }; + const filters = [ + { + meta: {}, + query: { + range: { + 'event.ingested': { format: 'strict_date_optional_time', gte: 'now-15m', lte: 'now' }, + }, + }, + }, + ]; + + const generateCsv = new CsvESQLGenerator( + createMockJob({ query, filters }), + mockConfig, + mockTaskInstanceFields, + { + es: mockEsClient, + data: mockDataClient, + uiSettings: uiSettingsClient, + }, + new CancellationToken(), + mockLogger, + stream + ); + await generateCsv.generateData(); + + expect(mockDataClient.search).toHaveBeenCalledWith( + { + params: { + filter: { + bool: { + filter: [ + { + range: { + 'event.ingested': { + format: 'strict_date_optional_time', + gte: 'now-15m', + lte: 'now', + }, + }, + }, + ], + must: [], + must_not: [], + should: [], + }, + }, + params: expect.arrayContaining([ + expect.objectContaining({ + _tstart: expect.any(String), + }), + expect.objectContaining({ + _tend: expect.any(String), + }), + ]), + locale: 'en', + query: query.esql, }, }, { @@ -508,7 +578,7 @@ describe('CsvESQLGenerator', () => { }); const generateCsv = new CsvESQLGenerator( - createMockJob(), + createMockJob({ query: { esql: '' } }), mockConfig, mockTaskInstanceFields, { @@ -538,7 +608,7 @@ describe('CsvESQLGenerator', () => { }); const generateCsv = new CsvESQLGenerator( - createMockJob(), + createMockJob({ query: { esql: '' } }), mockConfig, mockTaskInstanceFields, { @@ -576,7 +646,7 @@ describe('CsvESQLGenerator', () => { }); const generateCsv = new CsvESQLGenerator( - createMockJob(), + createMockJob({ query: { esql: '' } }), mockConfig, mockTaskInstanceFields, { @@ -605,7 +675,7 @@ describe('CsvESQLGenerator', () => { throw new Error('An unknown error'); }); const generateCsv = new CsvESQLGenerator( - createMockJob(), + createMockJob({ query: { esql: '' } }), mockConfig, mockTaskInstanceFields, { @@ -642,7 +712,7 @@ describe('CsvESQLGenerator', () => { }); const generateCsv = new CsvESQLGenerator( - createMockJob(), + createMockJob({ query: { esql: '' } }), mockConfig, mockTaskInstanceFields, { diff --git a/src/platform/packages/private/kbn-generate-csv/src/generate_csv_esql.ts b/src/platform/packages/private/kbn-generate-csv/src/generate_csv_esql.ts index 23dc3f8d4fda4..e47770374a991 100644 --- a/src/platform/packages/private/kbn-generate-csv/src/generate_csv_esql.ts +++ b/src/platform/packages/private/kbn-generate-csv/src/generate_csv_esql.ts @@ -14,7 +14,8 @@ import type { IScopedClusterClient, IUiSettingsClient, Logger } from '@kbn/core/ import type { IKibanaSearchResponse, IKibanaSearchRequest } from '@kbn/search-types'; import { ESQL_SEARCH_STRATEGY, cellHasFormulas, getEsQueryConfig } from '@kbn/data-plugin/common'; import type { IScopedSearchClient } from '@kbn/data-plugin/server'; -import { type Filter, buildEsQuery } from '@kbn/es-query'; +import { type Filter, buildEsQuery, extractTimeRange } from '@kbn/es-query'; +import { getTimeFieldFromESQLQuery, getStartEndParams } from '@kbn/esql-utils'; import type { ESQLSearchParams, ESQLSearchResponse } from '@kbn/es-types'; import { i18n } from '@kbn/i18n'; import { @@ -76,6 +77,17 @@ export class CsvESQLGenerator { const { maxSizeBytes, bom, escapeFormulaValues } = settings; const builder = new MaxSizeStringBuilder(this.stream, byteSizeValueToNumber(maxSizeBytes), bom); + // it will return undefined if there are no _tstart, _tend named params in the query + const timeFieldName = getTimeFieldFromESQLQuery(this.job.query.esql); + const params = []; + if (timeFieldName && this.job.filters) { + const { timeRange } = extractTimeRange(this.job.filters, timeFieldName); + if (timeRange) { + const namedParams = getStartEndParams(this.job.query.esql, timeRange); + params.push(...namedParams); + } + } + const filter = this.job.filters && buildEsQuery( @@ -91,6 +103,7 @@ export class CsvESQLGenerator { filter, // locale can be used for number/date formatting locale: i18n.getLocale(), + ...(params.length ? { params } : {}), // TODO: time_zone support was temporarily removed from ES|QL, // we will need to add it back in once it is supported again. // https://github.com/elastic/elasticsearch/pull/102767 diff --git a/src/platform/packages/private/kbn-generate-csv/tsconfig.json b/src/platform/packages/private/kbn-generate-csv/tsconfig.json index bc06d1769db7c..e781e93336a66 100644 --- a/src/platform/packages/private/kbn-generate-csv/tsconfig.json +++ b/src/platform/packages/private/kbn-generate-csv/tsconfig.json @@ -31,5 +31,6 @@ "@kbn/data-views-plugin", "@kbn/search-types", "@kbn/task-manager-plugin", + "@kbn/esql-utils", ] } diff --git a/src/platform/packages/shared/content-management/content_insights/content_insights_public/src/client.ts b/src/platform/packages/shared/content-management/content_insights/content_insights_public/src/client.ts index a46b01c01ac99..46fe68cece353 100644 --- a/src/platform/packages/shared/content-management/content_insights/content_insights_public/src/client.ts +++ b/src/platform/packages/shared/content-management/content_insights/content_insights_public/src/client.ts @@ -7,6 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ +import type { Logger } from '@kbn/logging'; import type { HttpStart } from '@kbn/core-http-browser'; import type { ContentInsightsStats, @@ -27,17 +28,21 @@ export interface ContentInsightsClientPublic { * Client for the Content Management Insights service. */ export class ContentInsightsClient implements ContentInsightsClientPublic { + private logger: Logger; constructor( - private readonly deps: { http: HttpStart }, + private readonly deps: { http: HttpStart; logger: Logger }, private readonly config: { domainId: string } - ) {} + ) { + this.logger = deps.logger.get('content_insights_client'); + } track(id: string, eventType: ContentInsightsEventTypes) { this.deps.http .post(`/internal/content_management/insights/${this.config.domainId}/${id}/${eventType}`) .catch((e) => { - // eslint-disable-next-line no-console - console.warn(`Could not track ${eventType} event for ${id}`, e); + this.logger.warn(`Could not track ${eventType} event for ${id}. Error: ${e?.message}`, { + error: e, + }); }); } diff --git a/src/platform/packages/shared/content-management/content_insights/content_insights_public/tsconfig.json b/src/platform/packages/shared/content-management/content_insights/content_insights_public/tsconfig.json index f93cc610ca877..b2953a0439776 100644 --- a/src/platform/packages/shared/content-management/content_insights/content_insights_public/tsconfig.json +++ b/src/platform/packages/shared/content-management/content_insights/content_insights_public/tsconfig.json @@ -29,5 +29,6 @@ "@kbn/content-management-content-insights-server", "@kbn/content-management-table-list-view-common", "@kbn/charts-theme", + "@kbn/logging", ] } diff --git a/src/platform/packages/shared/kbn-alerting-types/search_strategy_types.ts b/src/platform/packages/shared/kbn-alerting-types/search_strategy_types.ts index 9df72e4fa7886..51e1259091fa4 100644 --- a/src/platform/packages/shared/kbn-alerting-types/search_strategy_types.ts +++ b/src/platform/packages/shared/kbn-alerting-types/search_strategy_types.ts @@ -13,7 +13,7 @@ import type { QueryDslFieldAndFormat, QueryDslQueryContainer, SortCombinations, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import type { Alert } from './alert_type'; export type RuleRegistrySearchRequest = IEsSearchRequest & { diff --git a/src/platform/packages/shared/kbn-alerts-as-data-utils/src/schemas/generated/security_schema.ts b/src/platform/packages/shared/kbn-alerts-as-data-utils/src/schemas/generated/security_schema.ts index 58e1d8ebd1f46..ef774db2cf8db 100644 --- a/src/platform/packages/shared/kbn-alerts-as-data-utils/src/schemas/generated/security_schema.ts +++ b/src/platform/packages/shared/kbn-alerts-as-data-utils/src/schemas/generated/security_schema.ts @@ -212,6 +212,9 @@ const SecurityAlertOptional = rt.partial({ 'kibana.alert.workflow_tags': schemaStringArray, 'kibana.alert.workflow_user': schemaString, 'kibana.version': schemaString, + 'service.asset.criticality': schemaString, + 'service.risk.calculated_level': schemaString, + 'service.risk.calculated_score_norm': schemaNumber, tags: schemaStringArray, 'user.asset.criticality': schemaString, }); diff --git a/src/platform/packages/shared/kbn-alerts-ui-shared/src/alert_filter_controls/filter_group.test.tsx b/src/platform/packages/shared/kbn-alerts-ui-shared/src/alert_filter_controls/filter_group.test.tsx index 3d08697f98652..cfe5442f5473a 100644 --- a/src/platform/packages/shared/kbn-alerts-ui-shared/src/alert_filter_controls/filter_group.test.tsx +++ b/src/platform/packages/shared/kbn-alerts-ui-shared/src/alert_filter_controls/filter_group.test.tsx @@ -589,8 +589,14 @@ describe(' Filter Group Component ', () => { /> ); - expect(consoleErrorSpy.mock.calls.length).toBe(1); - expect(String(consoleErrorSpy.mock.calls[0][0])).toMatch(URL_PARAM_ARRAY_EXCEPTION_MSG); + const componentErrors = consoleErrorSpy.mock.calls.filter( + (c) => + !c[0]?.startsWith?.( + 'Warning: ReactDOM.render' + ) /* exclude react@18 legacy root warnings */ + ); + expect(componentErrors.length).toBe(1); + expect(String(componentErrors[0][0])).toMatch(URL_PARAM_ARRAY_EXCEPTION_MSG); }); }); diff --git a/src/platform/packages/shared/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.ts b/src/platform/packages/shared/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.ts index 232d1bf20fc68..412a5fa607110 100644 --- a/src/platform/packages/shared/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.ts +++ b/src/platform/packages/shared/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.ts @@ -20,7 +20,7 @@ import type { QueryDslFieldAndFormat, QueryDslQueryContainer, SortCombinations, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import type { EsQuerySnapshot, LegacyField } from '../../types'; export interface SearchAlertsParams { diff --git a/src/platform/packages/shared/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.ts b/src/platform/packages/shared/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.ts index e3c2d42a391e9..c0b022578d7be 100644 --- a/src/platform/packages/shared/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.ts +++ b/src/platform/packages/shared/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.ts @@ -16,7 +16,7 @@ import type { AggregationsAggregationContainer, QueryDslQueryContainer, SortCombinations, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import { BASE_RAC_ALERTS_API_PATH } from '../constants'; export interface UseGetAlertsGroupAggregationsQueryProps { diff --git a/src/platform/packages/shared/kbn-data-view-utils/src/utils/create_regexp_pattern_from.test.ts b/src/platform/packages/shared/kbn-data-view-utils/src/utils/create_regexp_pattern_from.test.ts index ea4b5a0c77a75..821e8b5a3d79a 100644 --- a/src/platform/packages/shared/kbn-data-view-utils/src/utils/create_regexp_pattern_from.test.ts +++ b/src/platform/packages/shared/kbn-data-view-utils/src/utils/create_regexp_pattern_from.test.ts @@ -10,7 +10,7 @@ import { createRegExpPatternFrom } from './create_regexp_pattern_from'; describe('createRegExpPatternFrom should create a regular expression starting from a string that', () => { - const regExpPattern = createRegExpPatternFrom('logs'); + const regExpPattern = createRegExpPatternFrom('logs', 'data'); it('tests positive for single index patterns starting with the passed base pattern', () => { expect('logs*').toMatch(regExpPattern); @@ -62,6 +62,52 @@ describe('createRegExpPatternFrom should create a regular expression starting fr expect('cluster1:logs-*,logs-*,').toMatch(regExpPattern); }); + it('tests correctly for patterns with the data selector suffix', () => { + expect('logs-*::data').toMatch(createRegExpPatternFrom('logs', 'data')); + expect('logs-*::data,').toMatch(createRegExpPatternFrom('logs', 'data')); + expect('cluster1:logs-*::data,logs-*::data').toMatch(createRegExpPatternFrom('logs', 'data')); + + expect('logs-*').not.toMatch(createRegExpPatternFrom('logs', 'failures')); + expect('logs-*::data').not.toMatch(createRegExpPatternFrom('logs', 'failures')); + expect('cluster1:logs-*::data,logs-*::data').not.toMatch( + createRegExpPatternFrom('logs', 'failures') + ); + + expect('logs-*').not.toMatch(createRegExpPatternFrom('logs', '*')); + expect('logs-*::data').not.toMatch(createRegExpPatternFrom('logs', '*')); + expect('cluster1:logs-*::data,logs-*::data').not.toMatch(createRegExpPatternFrom('logs', '*')); + }); + + it('tests correctly for patterns with the failures selector suffix', () => { + expect('logs-*::failures').toMatch(createRegExpPatternFrom('logs', 'failures')); + expect('logs-*::failures,').toMatch(createRegExpPatternFrom('logs', 'failures')); + expect('cluster1:logs-*::failures,logs-*::failures').toMatch( + createRegExpPatternFrom('logs', 'failures') + ); + + expect('logs-*::failures').not.toMatch(createRegExpPatternFrom('logs', 'data')); + expect('cluster1:logs-*::failures,logs-*::failures').not.toMatch( + createRegExpPatternFrom('logs', 'data') + ); + + expect('logs-*::failures').not.toMatch(createRegExpPatternFrom('logs', '*')); + expect('cluster1:logs-*::failures,logs-*::failures').not.toMatch( + createRegExpPatternFrom('logs', '*') + ); + }); + + it('tests correctly for patterns with the wildcard selector suffix', () => { + expect('logs-*::*').toMatch(createRegExpPatternFrom('logs', '*')); + expect('logs-*::*,').toMatch(createRegExpPatternFrom('logs', '*')); + expect('cluster1:logs-*::*,logs-*::*').toMatch(createRegExpPatternFrom('logs', '*')); + + expect('logs-*::*').not.toMatch(createRegExpPatternFrom('logs', 'data')); + expect('cluster1:logs-*::*,logs-*::*').not.toMatch(createRegExpPatternFrom('logs', 'data')); + + expect('logs-*::*').not.toMatch(createRegExpPatternFrom('logs', 'failures')); + expect('cluster1:logs-*::*,logs-*::*').not.toMatch(createRegExpPatternFrom('logs', 'failures')); + }); + it('tests negative for patterns with spaces and unexpected commas', () => { expect('cluster1:logs-*,clust,er2:logs-*').not.toMatch(regExpPattern); expect('cluster1:logs-*, cluster2:logs-*').not.toMatch(regExpPattern); diff --git a/src/platform/packages/shared/kbn-data-view-utils/src/utils/create_regexp_pattern_from.ts b/src/platform/packages/shared/kbn-data-view-utils/src/utils/create_regexp_pattern_from.ts index 35bb80612458c..b3d05b34737de 100644 --- a/src/platform/packages/shared/kbn-data-view-utils/src/utils/create_regexp_pattern_from.ts +++ b/src/platform/packages/shared/kbn-data-view-utils/src/utils/create_regexp_pattern_from.ts @@ -7,12 +7,31 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -export const createRegExpPatternFrom = (basePatterns: string | string[]) => { - const patterns = Array.isArray(basePatterns) ? basePatterns : [basePatterns]; - // Create the base patterns union with strict boundaries - const basePatternGroup = `[^,\\s]*(\\b|_)(${patterns.join('|')})(\\b|_)([^,\\s]*)?`; - // Apply base patterns union for local and remote clusters - const localAndRemotePatternGroup = `((${basePatternGroup})|([^:,\\s]*:${basePatternGroup}))`; - // Handle trailing comma and multiple pattern concatenation - return new RegExp(`^${localAndRemotePatternGroup}(,${localAndRemotePatternGroup})*(,$|$)`, 'i'); +import { escapeRegExp } from 'lodash'; + +type Selector = 'data' | 'failures' | '*'; + +export const createRegExpPatternFrom = (basePatterns: string | string[], selector: Selector) => { + const normalizedBasePatterns = normalizeBasePatterns(basePatterns); + + const indexNames = `(?:${normalizedBasePatterns.join('|')})`; + const selectorsSuffix = `(?:::(?:${escapeRegExp(selector)}))${ + isDefaultSelector(selector) ? '?' : '' + }`; + + return new RegExp( + `^(?:${optionalRemoteCluster}${optionalIndexNamePrefix}${indexNames}${optionalIndexNameSuffix}${selectorsSuffix},?)+$`, + 'i' + ); }; + +const normalizeBasePatterns = (basePatterns: string | string[]): string[] => + (Array.isArray(basePatterns) ? basePatterns : [basePatterns]).map(escapeRegExp); + +const isDefaultSelector = (selector: Selector): boolean => selector === 'data'; + +const nameCharacters = '[^:,\\s]+'; +const segmentBoundary = '(?:\\b|_)'; +const optionalRemoteCluster = `(?:${nameCharacters}:)?`; +const optionalIndexNamePrefix = `(?:${nameCharacters}${segmentBoundary})?`; +const optionalIndexNameSuffix = `(?:${segmentBoundary}${nameCharacters})?`; diff --git a/src/platform/packages/shared/kbn-discover-utils/src/data_types/logs/logs_context_service.ts b/src/platform/packages/shared/kbn-discover-utils/src/data_types/logs/logs_context_service.ts index 5f05def6d9c94..618ac31c6f1e5 100644 --- a/src/platform/packages/shared/kbn-discover-utils/src/data_types/logs/logs_context_service.ts +++ b/src/platform/packages/shared/kbn-discover-utils/src/data_types/logs/logs_context_service.ts @@ -28,7 +28,8 @@ export const DEFAULT_ALLOWED_LOGS_BASE_PATTERNS = [ ]; export const DEFAULT_ALLOWED_LOGS_BASE_PATTERNS_REGEXP = createRegExpPatternFrom( - DEFAULT_ALLOWED_LOGS_BASE_PATTERNS + DEFAULT_ALLOWED_LOGS_BASE_PATTERNS, + 'data' ); export const createLogsContextService = async ({ logsDataAccess }: LogsContextServiceDeps) => { diff --git a/src/platform/packages/shared/kbn-doc-links/src/get_doc_links.ts b/src/platform/packages/shared/kbn-doc-links/src/get_doc_links.ts index 1a56dc0020b6b..cdde09834da34 100644 --- a/src/platform/packages/shared/kbn-doc-links/src/get_doc_links.ts +++ b/src/platform/packages/shared/kbn-doc-links/src/get_doc_links.ts @@ -448,6 +448,7 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D detectionEngineOverview: `${SECURITY_SOLUTION_DOCS}detection-engine-overview.html`, aiAssistant: `${SECURITY_SOLUTION_DOCS}security-assistant.html`, signalsMigrationApi: `${SECURITY_SOLUTION_DOCS}signals-migration-api.html`, + legacyEndpointManagementApiDeprecations: `${KIBANA_DOCS}breaking-changes-summary.html#breaking-199598`, }, query: { eql: `${ELASTICSEARCH_DOCS}eql.html`, diff --git a/src/platform/packages/shared/kbn-doc-links/src/types.ts b/src/platform/packages/shared/kbn-doc-links/src/types.ts index c22a9e9edd1e0..c0aa9084367d6 100644 --- a/src/platform/packages/shared/kbn-doc-links/src/types.ts +++ b/src/platform/packages/shared/kbn-doc-links/src/types.ts @@ -314,6 +314,7 @@ export interface DocLinks { }; readonly detectionEngineOverview: string; readonly signalsMigrationApi: string; + readonly legacyEndpointManagementApiDeprecations: string; }; readonly query: { readonly eql: string; diff --git a/src/platform/packages/shared/kbn-es-query/src/filters/helpers/convert_range_filter.test.ts b/src/platform/packages/shared/kbn-es-query/src/filters/helpers/convert_range_filter.test.ts index e1989518582c3..e5195bcf6066a 100644 --- a/src/platform/packages/shared/kbn-es-query/src/filters/helpers/convert_range_filter.test.ts +++ b/src/platform/packages/shared/kbn-es-query/src/filters/helpers/convert_range_filter.test.ts @@ -24,4 +24,28 @@ describe('convertRangeFilterToTimeRange', () => { expect(convertedRangeFilter).toEqual(filterAfterConvertedRangeFilter); }); + + it('should return converted range for relative dates', () => { + const filter: any = { query: { range: { '@timestamp': { gte: 'now-1d', lte: 'now' } } } }; + const filterAfterConvertedRangeFilter = { + from: 'now-1d', + to: 'now', + }; + const convertedRangeFilter = convertRangeFilterToTimeRange(filter); + + expect(convertedRangeFilter).toEqual(filterAfterConvertedRangeFilter); + }); + + it('should return converted range for relative dates without now', () => { + const filter: any = { + query: { range: { '@timestamp': { gte: '2024.02.01', lte: '2024.02.01||+1M/d' } } }, + }; + const filterAfterConvertedRangeFilter = { + from: moment('2024.02.01'), + to: '2024.02.01||+1M/d', + }; + const convertedRangeFilter = convertRangeFilterToTimeRange(filter); + + expect(convertedRangeFilter).toEqual(filterAfterConvertedRangeFilter); + }); }); diff --git a/src/platform/packages/shared/kbn-es-query/src/filters/helpers/convert_range_filter.ts b/src/platform/packages/shared/kbn-es-query/src/filters/helpers/convert_range_filter.ts index b5a58ba528852..88b8f5f8a35ec 100644 --- a/src/platform/packages/shared/kbn-es-query/src/filters/helpers/convert_range_filter.ts +++ b/src/platform/packages/shared/kbn-es-query/src/filters/helpers/convert_range_filter.ts @@ -12,20 +12,26 @@ import { keys } from 'lodash'; import type { RangeFilter } from '../build_filters'; import type { TimeRange } from './types'; +const isRelativeTime = (value: string | number | undefined): boolean => { + return typeof value === 'string' && !moment(value).isValid(); +}; + export function convertRangeFilterToTimeRange(filter: RangeFilter) { const key = keys(filter.query.range)[0]; const values = filter.query.range[key]; + const from = values.gt || values.gte; + const to = values.lt || values.lte; return { - from: moment(values.gt || values.gte), - to: moment(values.lt || values.lte), + from: from && isRelativeTime(from) ? String(from) : moment(from), + to: to && isRelativeTime(to) ? String(to) : moment(to), }; } export function convertRangeFilterToTimeRangeString(filter: RangeFilter): TimeRange { const { from, to } = convertRangeFilterToTimeRange(filter); return { - from: from?.toISOString(), - to: to?.toISOString(), + from: moment.isMoment(from) ? from?.toISOString() : from, + to: moment.isMoment(to) ? to?.toISOString() : to, }; } diff --git a/src/platform/packages/shared/kbn-grouping/src/containers/query/types.ts b/src/platform/packages/shared/kbn-grouping/src/containers/query/types.ts index 46e6af5855bb5..9956fdb35deb4 100644 --- a/src/platform/packages/shared/kbn-grouping/src/containers/query/types.ts +++ b/src/platform/packages/shared/kbn-grouping/src/containers/query/types.ts @@ -11,10 +11,10 @@ import type { Script, MappingRuntimeField, MappingRuntimeFields, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import type { RuntimeFieldSpec, RuntimePrimitiveTypes } from '@kbn/data-views-plugin/common'; import type { BoolQuery } from '@kbn/es-query'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; type RunTimeMappings = | Record & { type: RuntimePrimitiveTypes }> diff --git a/src/platform/packages/shared/kbn-saved-search-component/src/components/saved_search.tsx b/src/platform/packages/shared/kbn-saved-search-component/src/components/saved_search.tsx index 5172d5c5e0210..ecd3a4f18aa9a 100644 --- a/src/platform/packages/shared/kbn-saved-search-component/src/components/saved_search.tsx +++ b/src/platform/packages/shared/kbn-saved-search-component/src/components/saved_search.tsx @@ -15,7 +15,7 @@ import type { SearchEmbeddableRuntimeState, SearchEmbeddableApi, } from '@kbn/discover-plugin/public'; -import { SerializedPanelState } from '@kbn/presentation-containers'; +import { SerializedPanelState } from '@kbn/presentation-publishing'; import { css } from '@emotion/react'; import { SavedSearchComponentProps } from '../types'; import { SavedSearchComponentErrorContent } from './error'; diff --git a/src/platform/packages/shared/kbn-saved-search-component/tsconfig.json b/src/platform/packages/shared/kbn-saved-search-component/tsconfig.json index 2fc2b3d2e9b53..5850d6fcf9b81 100644 --- a/src/platform/packages/shared/kbn-saved-search-component/tsconfig.json +++ b/src/platform/packages/shared/kbn-saved-search-component/tsconfig.json @@ -23,7 +23,7 @@ "@kbn/es-query", "@kbn/data-plugin", "@kbn/discover-plugin", - "@kbn/presentation-containers", "@kbn/i18n", + "@kbn/presentation-publishing", ] } diff --git a/src/platform/packages/shared/kbn-securitysolution-ecs/src/index.ts b/src/platform/packages/shared/kbn-securitysolution-ecs/src/index.ts index fea77a4bc188f..180c3d1565dc2 100644 --- a/src/platform/packages/shared/kbn-securitysolution-ecs/src/index.ts +++ b/src/platform/packages/shared/kbn-securitysolution-ecs/src/index.ts @@ -37,6 +37,7 @@ import type { UrlEcs } from './url'; import type { UserEcs } from './user'; import type { WinlogEcs } from './winlog'; import type { ZeekEcs } from './zeek'; +import type { ServiceEcs } from './service'; export * from './ecs_fields'; export { EventCategory, EventCode }; @@ -74,6 +75,7 @@ export type { UserEcs, WinlogEcs, ZeekEcs, + ServiceEcs, }; // Security Solution Extension of the Elastic Common Schema @@ -97,6 +99,7 @@ export interface EcsSecurityExtension { tls?: TlsEcs; url?: UrlEcs; user?: UserEcs; + service?: ServiceEcs; // Security Specific Ecs // exists only in security solution Ecs definition diff --git a/src/platform/packages/shared/kbn-securitysolution-ecs/src/service/index.ts b/src/platform/packages/shared/kbn-securitysolution-ecs/src/service/index.ts new file mode 100644 index 0000000000000..99ad3140565ae --- /dev/null +++ b/src/platform/packages/shared/kbn-securitysolution-ecs/src/service/index.ts @@ -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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export interface ServiceEcs { + address?: string[]; + environment?: string[]; + ephemeral_id?: string[]; + id?: string[]; + name?: string[]; + node?: { + name: string[]; + roles: string[]; + role: string[]; + }; + roles?: string[]; + state?: string[]; + type?: string[]; + version?: string[]; +} diff --git a/src/platform/packages/shared/kbn-typed-react-router-config/src/breadcrumbs/use_breadcrumbs.ts b/src/platform/packages/shared/kbn-typed-react-router-config/src/breadcrumbs/use_breadcrumbs.ts index 3d63c8a0f27d7..26123f35b15e7 100644 --- a/src/platform/packages/shared/kbn-typed-react-router-config/src/breadcrumbs/use_breadcrumbs.ts +++ b/src/platform/packages/shared/kbn-typed-react-router-config/src/breadcrumbs/use_breadcrumbs.ts @@ -13,11 +13,12 @@ import { MouseEvent, useEffect, useMemo } from 'react'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { ChromeBreadcrumbsAppendExtension } from '@kbn/core-chrome-browser'; import type { ServerlessPluginStart } from '@kbn/serverless/public'; +import useObservable from 'react-use/lib/useObservable'; function addClickHandlers( breadcrumbs: ChromeBreadcrumb[], navigateToHref?: (url: string) => Promise -) { +): ChromeBreadcrumb[] { return breadcrumbs.map((bc) => ({ ...bc, ...(bc.href @@ -49,7 +50,12 @@ export const useBreadcrumbs = ( const { services: { - chrome: { docTitle, setBreadcrumbs: chromeSetBreadcrumbs, setBreadcrumbsAppendExtension }, + chrome: { + docTitle, + setBreadcrumbs: chromeSetBreadcrumbs, + setBreadcrumbsAppendExtension, + getChromeStyle$, + }, application: { getUrlForApp, navigateToUrl }, }, } = useKibana<{ @@ -57,6 +63,9 @@ export const useBreadcrumbs = ( chrome: ChromeStart; }>(); + const chromeStyle = useObservable(getChromeStyle$()); + const isProjectNavigation = chromeStyle === 'project'; + const setTitle = docTitle.change; const appPath = getUrlForApp(app?.id ?? 'observability-overview') ?? ''; @@ -77,7 +86,7 @@ export const useBreadcrumbs = ( }, [breadcrumbsAppendExtension, setBreadcrumbsAppendExtension]); useEffect(() => { - const breadcrumbs = serverless + const breadcrumbs = isProjectNavigation ? extraCrumbs : [ { @@ -92,10 +101,25 @@ export const useBreadcrumbs = ( ]; if (setBreadcrumbs) { - setBreadcrumbs(addClickHandlers(breadcrumbs, navigateToUrl)); + const breadcrumbsWithClickHandlers = addClickHandlers(breadcrumbs, navigateToUrl); + setBreadcrumbs(breadcrumbsWithClickHandlers, { + project: { + value: breadcrumbsWithClickHandlers, + absolute: true, + }, + }); } if (setTitle) { setTitle(getTitleFromBreadCrumbs(breadcrumbs)); } - }, [app?.label, appPath, extraCrumbs, navigateToUrl, serverless, setBreadcrumbs, setTitle]); + }, [ + app?.label, + isProjectNavigation, + appPath, + extraCrumbs, + navigateToUrl, + serverless, + setBreadcrumbs, + setTitle, + ]); }; diff --git a/src/platform/packages/shared/presentation/presentation_containers/index.ts b/src/platform/packages/shared/presentation/presentation_containers/index.ts index 833e8f5b4a0c2..4ddbe46329f4d 100644 --- a/src/platform/packages/shared/presentation/presentation_containers/index.ts +++ b/src/platform/packages/shared/presentation/presentation_containers/index.ts @@ -39,10 +39,4 @@ export { type PresentationContainer, } from './interfaces/presentation_container'; export { apiPublishesSettings, type PublishesSettings } from './interfaces/publishes_settings'; -export { - apiHasSerializableState, - type HasSerializableState, - type HasSnapshottableState, - type SerializedPanelState, -} from './interfaces/serialized_state'; export { tracksOverlays, type TracksOverlays } from './interfaces/tracks_overlays'; diff --git a/src/platform/packages/shared/presentation/presentation_containers/interfaces/child_state.ts b/src/platform/packages/shared/presentation/presentation_containers/interfaces/child_state.ts index adc709f327318..4245b48904314 100644 --- a/src/platform/packages/shared/presentation/presentation_containers/interfaces/child_state.ts +++ b/src/platform/packages/shared/presentation/presentation_containers/interfaces/child_state.ts @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { SerializedPanelState } from './serialized_state'; +import { SerializedPanelState } from '@kbn/presentation-publishing'; export interface HasSerializedChildState { getSerializedStateForChild: ( @@ -15,6 +15,9 @@ export interface HasSerializedChildState SerializedPanelState | undefined; } +/** + * @deprecated Use `HasSerializedChildState` instead. All interactions between the container and the child should use the serialized state. + */ export interface HasRuntimeChildState { getRuntimeStateForChild: (childId: string) => Partial | undefined; } @@ -24,7 +27,9 @@ export const apiHasSerializedChildState = => { return Boolean(api && (api as HasSerializedChildState).getSerializedStateForChild); }; - +/** + * @deprecated Use `HasSerializedChildState` instead. All interactions between the container and the child should use the serialized state. + */ export const apiHasRuntimeChildState = ( api: unknown ): api is HasRuntimeChildState => { diff --git a/src/platform/packages/shared/presentation/presentation_containers/interfaces/presentation_container.ts b/src/platform/packages/shared/presentation/presentation_containers/interfaces/presentation_container.ts index 47368b0e6009b..7b76260aad188 100644 --- a/src/platform/packages/shared/presentation/presentation_containers/interfaces/presentation_container.ts +++ b/src/platform/packages/shared/presentation/presentation_containers/interfaces/presentation_container.ts @@ -7,13 +7,30 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { apiHasParentApi, apiHasUniqueId, PublishingSubject } from '@kbn/presentation-publishing'; +import { + apiHasParentApi, + apiHasUniqueId, + PublishingSubject, + SerializedPanelState, +} from '@kbn/presentation-publishing'; import { BehaviorSubject, combineLatest, isObservable, map, Observable, of, switchMap } from 'rxjs'; import { apiCanAddNewPanel, CanAddNewPanel } from './can_add_new_panel'; -export interface PanelPackage { +export interface PanelPackage< + SerializedStateType extends object = object, + RuntimeStateType extends object = object +> { panelType: string; - initialState?: SerializedState; + + /** + * The serialized state of this panel. + */ + serializedState?: SerializedPanelState; + + /** + * The runtime state of this panel. @deprecated Use `serializedState` instead. + */ + initialState?: RuntimeStateType; } export interface PresentationContainer extends CanAddNewPanel { diff --git a/src/platform/packages/shared/presentation/presentation_containers/interfaces/unsaved_changes/initialize_unsaved_changes.ts b/src/platform/packages/shared/presentation/presentation_containers/interfaces/unsaved_changes/initialize_unsaved_changes.ts index fb767fb11cffd..e28ff77f88e00 100644 --- a/src/platform/packages/shared/presentation/presentation_containers/interfaces/unsaved_changes/initialize_unsaved_changes.ts +++ b/src/platform/packages/shared/presentation/presentation_containers/interfaces/unsaved_changes/initialize_unsaved_changes.ts @@ -21,8 +21,8 @@ import { PublishingSubject, runComparators, StateComparators, + HasSnapshottableState, } from '@kbn/presentation-publishing'; -import { HasSnapshottableState } from '../serialized_state'; import { apiHasSaveNotification } from '../has_save_notification'; export const COMPARATOR_SUBJECTS_DEBOUNCE = 100; diff --git a/src/platform/packages/shared/presentation/presentation_containers/tsconfig.json b/src/platform/packages/shared/presentation/presentation_containers/tsconfig.json index e6e2a00a07655..e138a22926a89 100644 --- a/src/platform/packages/shared/presentation/presentation_containers/tsconfig.json +++ b/src/platform/packages/shared/presentation/presentation_containers/tsconfig.json @@ -9,6 +9,5 @@ "kbn_references": [ "@kbn/presentation-publishing", "@kbn/core-mount-utils-browser", - "@kbn/content-management-utils", ] } diff --git a/src/platform/packages/shared/presentation/presentation_publishing/index.ts b/src/platform/packages/shared/presentation/presentation_publishing/index.ts index 62e68521a5b09..e24a2d26ba403 100644 --- a/src/platform/packages/shared/presentation/presentation_publishing/index.ts +++ b/src/platform/packages/shared/presentation/presentation_publishing/index.ts @@ -64,14 +64,17 @@ export { type HasExecutionContext, } from './interfaces/has_execution_context'; export { - apiHasInPlaceLibraryTransforms, - apiHasLegacyLibraryTransforms, apiHasLibraryTransforms, - type HasInPlaceLibraryTransforms, - type HasLegacyLibraryTransforms, type HasLibraryTransforms, } from './interfaces/has_library_transforms'; export { apiHasParentApi, type HasParentApi } from './interfaces/has_parent_api'; +export { + apiHasSerializableState, + apiHasSnapshottableState, + type HasSerializableState, + type HasSnapshottableState, + type SerializedPanelState, +} from './interfaces/has_serializable_state'; export { apiHasSupportedTriggers, type HasSupportedTriggers, diff --git a/src/platform/packages/shared/presentation/presentation_publishing/interfaces/has_library_transforms.ts b/src/platform/packages/shared/presentation/presentation_publishing/interfaces/has_library_transforms.ts index b90faefe38f6e..38734f46b0093 100644 --- a/src/platform/packages/shared/presentation/presentation_publishing/interfaces/has_library_transforms.ts +++ b/src/platform/packages/shared/presentation/presentation_publishing/interfaces/has_library_transforms.ts @@ -7,101 +7,57 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { PublishingSubject } from '../publishing_subject'; +import { SerializedPanelState } from './has_serializable_state'; -interface DuplicateTitleCheck { +/** + * APIs that inherit this interface can be linked to and unlinked from the library. + */ +export interface HasLibraryTransforms< + ByReferenceSerializedState extends object = object, + ByValueSerializedState extends object = object +> { checkForDuplicateTitle: ( newTitle: string, isTitleDuplicateConfirmed: boolean, onTitleDuplicate: () => void ) => Promise; -} -interface LibraryTransformGuards { + /** * * @returns {Promise} - * True when embeddable is by-value and can be converted to by-reference + * Returns true when this API is by-value and can be converted to by-reference */ canLinkToLibrary: () => Promise; + /** * * @returns {Promise} - * True when embeddable is by-reference and can be converted to by-value + * Returns true when this API is by-reference and can be converted to by-value */ canUnlinkFromLibrary: () => Promise; -} - -/** - * APIs that inherit this interface can be linked to and unlinked from the library in place without - * re-initialization. - */ -export interface HasInPlaceLibraryTransforms - extends Partial, - DuplicateTitleCheck { - /** - * The id of the library item that this embeddable is linked to. - */ - libraryId$: PublishingSubject; /** - * Save embeddable to library + * Save the state of this API to the library. This will return the ID of the persisted library item. * * @returns {Promise} id of persisted library item */ saveToLibrary: (title: string) => Promise; /** - * gets a snapshot of this embeddable's runtime state without any state that links it to a library item. - */ - getByValueRuntimeSnapshot: () => RuntimeState; - - /** - * Un-links this embeddable from the library. This method is optional, and only needed if the Embeddable - * is not meant to be re-initialized as part of the unlink operation. If the embeddable needs to be re-initialized - * after unlinking, the getByValueState method should be used instead. - */ - unlinkFromLibrary: () => void; -} - -export const apiHasInPlaceLibraryTransforms = ( - unknownApi: null | unknown -): unknownApi is HasInPlaceLibraryTransforms => { - return Boolean( - unknownApi && - Boolean((unknownApi as HasInPlaceLibraryTransforms)?.libraryId$) && - typeof (unknownApi as HasInPlaceLibraryTransforms).saveToLibrary === 'function' && - typeof (unknownApi as HasInPlaceLibraryTransforms).unlinkFromLibrary === 'function' - ); -}; - -/** - * @deprecated use HasInPlaceLibraryTransforms instead - * APIs that inherit this interface can be linked to and unlinked from the library. After the save or unlink - * operation, the embeddable will be reinitialized. - */ -export interface HasLibraryTransforms - extends LibraryTransformGuards, - DuplicateTitleCheck { - /** - * Save embeddable to library * - * @returns {Promise} id of persisted library item + * @returns {ByReferenceSerializedState} + * get by-reference serialized state from this API. */ - saveToLibrary: (title: string) => Promise; - /** - * - * @returns {StateT} - * by-reference embeddable state replacing by-value embeddable state. After - * the save operation, the embeddable will be reinitialized with the results of this method. - */ - getByReferenceState: (libraryId: string) => StateT; + getSerializedStateByReference: ( + newId: string + ) => SerializedPanelState; + /** * - * @returns {StateT} - * by-value embeddable state replacing by-reference embeddable state. After - * the unlink operation, the embeddable will be reinitialized with the results of this method. + * @returns {ByValueSerializedState} + * get by-value serialized state from this API */ - getByValueState: () => StateT; + getSerializedStateByValue: () => SerializedPanelState; } export const apiHasLibraryTransforms = ( @@ -112,34 +68,10 @@ export const apiHasLibraryTransforms = ( typeof (unknownApi as HasLibraryTransforms).canLinkToLibrary === 'function' && typeof (unknownApi as HasLibraryTransforms).canUnlinkFromLibrary === 'function' && typeof (unknownApi as HasLibraryTransforms).saveToLibrary === 'function' && - typeof (unknownApi as HasLibraryTransforms).getByReferenceState === 'function' && - typeof (unknownApi as HasLibraryTransforms).getByValueState === 'function' && + typeof (unknownApi as HasLibraryTransforms).getSerializedStateByReference === + 'function' && + typeof (unknownApi as HasLibraryTransforms).getSerializedStateByValue === + 'function' && typeof (unknownApi as HasLibraryTransforms).checkForDuplicateTitle === 'function' ); }; - -/** - * @deprecated use HasLibraryTransforms instead - */ -export type HasLegacyLibraryTransforms = Pick< - HasLibraryTransforms, - 'canLinkToLibrary' | 'canUnlinkFromLibrary' -> & { - linkToLibrary: () => Promise; - unlinkFromLibrary: () => Promise; -}; - -/** - * @deprecated use apiHasLibraryTransforms instead - */ -export const apiHasLegacyLibraryTransforms = ( - unknownApi: null | unknown -): unknownApi is HasLegacyLibraryTransforms => { - return Boolean( - unknownApi && - typeof (unknownApi as HasLegacyLibraryTransforms).canLinkToLibrary === 'function' && - typeof (unknownApi as HasLegacyLibraryTransforms).canUnlinkFromLibrary === 'function' && - typeof (unknownApi as HasLegacyLibraryTransforms).linkToLibrary === 'function' && - typeof (unknownApi as HasLegacyLibraryTransforms).unlinkFromLibrary === 'function' - ); -}; diff --git a/src/platform/packages/shared/presentation/presentation_containers/interfaces/serialized_state.ts b/src/platform/packages/shared/presentation/presentation_publishing/interfaces/has_serializable_state.ts similarity index 93% rename from src/platform/packages/shared/presentation/presentation_containers/interfaces/serialized_state.ts rename to src/platform/packages/shared/presentation/presentation_publishing/interfaces/has_serializable_state.ts index 0368bd751ce78..f6144d78ae19f 100644 --- a/src/platform/packages/shared/presentation/presentation_containers/interfaces/serialized_state.ts +++ b/src/platform/packages/shared/presentation/presentation_publishing/interfaces/has_serializable_state.ts @@ -30,6 +30,9 @@ export const apiHasSerializableState = (api: unknown | null): api is HasSerializ return Boolean((api as HasSerializableState)?.serializeState); }; +/** + * @deprecated use HasSerializableState instead + */ export interface HasSnapshottableState { /** * Serializes all runtime state exactly as it appears. This can be used @@ -38,6 +41,9 @@ export interface HasSnapshottableState { snapshotRuntimeState: () => RuntimeState; } +/** + * @deprecated use apiHasSerializableState instead + */ export const apiHasSnapshottableState = (api: unknown | null): api is HasSnapshottableState => { return Boolean((api as HasSnapshottableState)?.snapshotRuntimeState); }; diff --git a/src/platform/packages/shared/presentation/presentation_publishing/tsconfig.json b/src/platform/packages/shared/presentation/presentation_publishing/tsconfig.json index 58edc9d14270d..44a58006f60c4 100644 --- a/src/platform/packages/shared/presentation/presentation_publishing/tsconfig.json +++ b/src/platform/packages/shared/presentation/presentation_publishing/tsconfig.json @@ -10,6 +10,7 @@ "@kbn/es-query", "@kbn/data-views-plugin", "@kbn/expressions-plugin", - "@kbn/core-execution-context-common" + "@kbn/core-execution-context-common", + "@kbn/content-management-utils" ] } diff --git a/src/platform/plugins/private/links/public/embeddable/links_embeddable.test.tsx b/src/platform/plugins/private/links/public/embeddable/links_embeddable.test.tsx index 7bbb7b52e66b6..3c949da0a3277 100644 --- a/src/platform/plugins/private/links/public/embeddable/links_embeddable.test.tsx +++ b/src/platform/plugins/private/links/public/embeddable/links_embeddable.test.tsx @@ -217,7 +217,7 @@ describe('getLinksEmbeddableFactory', () => { }, references: [], }); - expect(api.libraryId$.value).toBe('123'); + expect(await api.canUnlinkFromLibrary()).toBe(true); expect(api.defaultPanelTitle!.value).toBe('links 001'); expect(api.defaultPanelDescription!.value).toBe('some links'); }); @@ -236,8 +236,7 @@ describe('getLinksEmbeddableFactory', () => { await waitFor(async () => { const api = onApiAvailable.mock.calls[0][0]; - api.unlinkFromLibrary(); - expect(await api.serializeState()).toEqual({ + expect(await api.getSerializedStateByValue()).toEqual({ rawState: { title: 'my links', description: 'just a few links', @@ -251,7 +250,6 @@ describe('getLinksEmbeddableFactory', () => { }, references, }); - expect(api.libraryId$.value).toBeUndefined(); }); }); }); @@ -329,7 +327,7 @@ describe('getLinksEmbeddableFactory', () => { references, }); - expect(api.libraryId$.value).toBeUndefined(); + expect(await api.canLinkToLibrary()).toBe(true); }); }); test('save to library', async () => { @@ -355,8 +353,7 @@ describe('getLinksEmbeddableFactory', () => { options: { references }, }); expect(newId).toBe('333'); - expect(api.libraryId$.value).toBe('333'); - expect(await api.serializeState()).toEqual({ + expect(await api.getSerializedStateByReference(newId)).toEqual({ rawState: { savedObjectId: '333', title: 'my links', diff --git a/src/platform/plugins/private/links/public/embeddable/links_embeddable.tsx b/src/platform/plugins/private/links/public/embeddable/links_embeddable.tsx index a1bff3702c6ce..36bf21cb1a65b 100644 --- a/src/platform/plugins/private/links/public/embeddable/links_embeddable.tsx +++ b/src/platform/plugins/private/links/public/embeddable/links_embeddable.tsx @@ -10,17 +10,16 @@ import React, { createContext, useMemo } from 'react'; import { cloneDeep } from 'lodash'; import { BehaviorSubject } from 'rxjs'; -import fastIsEqual from 'fast-deep-equal'; import { EuiListGroup, EuiPanel } from '@elastic/eui'; import { PanelIncompatibleError, ReactEmbeddableFactory } from '@kbn/embeddable-plugin/public'; import { + SerializedTitles, initializeTitles, + SerializedPanelState, useBatchedOptionalPublishingSubjects, } from '@kbn/presentation-publishing'; -import { SerializedPanelState } from '@kbn/presentation-containers'; - import { CONTENT_ID, DASHBOARD_LINK_TYPE, @@ -105,8 +104,27 @@ export const getLinksEmbeddableFactory = () => { state.defaultPanelDescription ); const savedObjectId$ = new BehaviorSubject(state.savedObjectId); + const isByReference = Boolean(state.savedObjectId); + const { titlesApi, titleComparators, serializeTitles } = initializeTitles(state); + const serializeLinksState = (byReference: boolean, newId?: string) => { + if (byReference) { + const linksByReferenceState: LinksByReferenceSerializedState = { + savedObjectId: newId ?? state.savedObjectId!, + ...serializeTitles(), + }; + return { rawState: linksByReferenceState, references: [] }; + } + const runtimeState = api.snapshotRuntimeState(); + const { attributes, references } = serializeLinksAttributes(runtimeState); + const linksByValueState: LinksByValueSerializedState = { + attributes, + ...serializeTitles(), + }; + return { rawState: linksByValueState, references }; + }; + const api = buildApi( { ...titlesApi, @@ -114,29 +132,8 @@ export const getLinksEmbeddableFactory = () => { defaultPanelTitle, defaultPanelDescription, isEditingEnabled: () => Boolean(error$.value === undefined), - libraryId$: savedObjectId$, getTypeDisplayName: () => DISPLAY_NAME, - getByValueRuntimeSnapshot: () => { - const snapshot = api.snapshotRuntimeState(); - delete snapshot.savedObjectId; - return snapshot; - }, - serializeState: (): SerializedPanelState => { - if (savedObjectId$.value !== undefined) { - const linksByReferenceState: LinksByReferenceSerializedState = { - savedObjectId: savedObjectId$.value, - ...serializeTitles(), - }; - return { rawState: linksByReferenceState, references: [] }; - } - const runtimeState = api.snapshotRuntimeState(); - const { attributes, references } = serializeLinksAttributes(runtimeState); - const linksByValueState: LinksByValueSerializedState = { - attributes, - ...serializeTitles(), - }; - return { rawState: linksByValueState, references }; - }, + serializeState: () => serializeLinksState(isByReference), saveToLibrary: async (newTitle: string) => { defaultPanelTitle.next(newTitle); const runtimeState = api.snapshotRuntimeState(); @@ -150,9 +147,17 @@ export const getLinksEmbeddableFactory = () => { }, options: { references }, }); - savedObjectId$.next(id); return id; }, + getSerializedStateByValue: () => + serializeLinksState(false) as SerializedPanelState, + getSerializedStateByReference: (newId: string) => + serializeLinksState( + true, + newId + ) as SerializedPanelState, + canLinkToLibrary: async () => !isByReference, + canUnlinkFromLibrary: async () => isByReference, checkForDuplicateTitle: async ( newTitle: string, isTitleDuplicateConfirmed: boolean, @@ -166,36 +171,41 @@ export const getLinksEmbeddableFactory = () => { onTitleDuplicate, }); }, - unlinkFromLibrary: () => { - savedObjectId$.next(undefined); - }, onEdit: async () => { const { openEditorFlyout } = await import('../editor/open_editor_flyout'); const newState = await openEditorFlyout({ initialState: api.snapshotRuntimeState(), parentDashboard: parentApi, }); + if (!newState) return; + + // if the by reference state has changed during this edit, reinitialize the panel. + const nextIsByReference = Boolean(newState?.savedObjectId); + if (nextIsByReference !== isByReference) { + const serializedState = serializeLinksState( + nextIsByReference, + newState?.savedObjectId + ); + (serializedState.rawState as SerializedTitles).title = newState.title; - if (newState) { - links$.next(newState.links); - layout$.next(newState.layout); - defaultPanelTitle.next(newState.defaultPanelTitle); - defaultPanelDescription.next(newState.defaultPanelDescription); - savedObjectId$.next(newState.savedObjectId); + api.parentApi?.replacePanel(api.uuid, { + serializedState, + panelType: api.type, + }); + return; } + links$.next(newState.links); + layout$.next(newState.layout); + defaultPanelTitle.next(newState.defaultPanelTitle); + defaultPanelDescription.next(newState.defaultPanelDescription); }, }, { ...titleComparators, - links: [ - links$, - (nextLinks?: ResolvedLink[]) => links$.next(nextLinks ?? []), - (a, b) => Boolean(savedObjectId$.value) || fastIsEqual(a, b), // Editing attributes in a by-reference panel should not trigger unsaved changes. - ], + links: [links$, (nextLinks?: ResolvedLink[]) => links$.next(nextLinks ?? [])], layout: [ layout$, (nextLayout?: LinksLayoutType) => layout$.next(nextLayout ?? LINKS_VERTICAL_LAYOUT), - (a, b) => Boolean(savedObjectId$.value) || a === b, ], error: [error$, (nextError?: Error) => error$.next(nextError)], defaultPanelDescription: [ diff --git a/src/platform/plugins/private/links/public/types.ts b/src/platform/plugins/private/links/public/types.ts index d4b88ca5b7c51..90d545ac1cc1c 100644 --- a/src/platform/plugins/private/links/public/types.ts +++ b/src/platform/plugins/private/links/public/types.ts @@ -9,7 +9,7 @@ import { HasEditCapabilities, - HasInPlaceLibraryTransforms, + HasLibraryTransforms, HasType, PublishesPanelDescription, PublishesPanelTitle, @@ -40,7 +40,7 @@ export type LinksParentApi = PresentationContainer & export type LinksApi = HasType & DefaultEmbeddableApi & HasEditCapabilities & - HasInPlaceLibraryTransforms; + HasLibraryTransforms; export interface LinksByReferenceSerializedState { savedObjectId: string; diff --git a/src/platform/plugins/private/presentation_panel/public/panel_actions/index.ts b/src/platform/plugins/private/presentation_panel/public/panel_actions/index.ts index 43a3ac116cf93..a9f14d09350ca 100644 --- a/src/platform/plugins/private/presentation_panel/public/panel_actions/index.ts +++ b/src/platform/plugins/private/presentation_panel/public/panel_actions/index.ts @@ -11,9 +11,7 @@ export { contextMenuTrigger, CONTEXT_MENU_TRIGGER, panelBadgeTrigger, - panelHoverTrigger, panelNotificationTrigger, PANEL_BADGE_TRIGGER, - PANEL_HOVER_TRIGGER, PANEL_NOTIFICATION_TRIGGER, } from './triggers'; diff --git a/src/platform/plugins/private/presentation_panel/public/panel_actions/triggers.ts b/src/platform/plugins/private/presentation_panel/public/panel_actions/triggers.ts index 18c98074486d9..79c1157ccecad 100644 --- a/src/platform/plugins/private/presentation_panel/public/panel_actions/triggers.ts +++ b/src/platform/plugins/private/presentation_panel/public/panel_actions/triggers.ts @@ -21,17 +21,6 @@ export const contextMenuTrigger: Trigger = { }), }; -export const PANEL_HOVER_TRIGGER = 'PANEL_HOVER_TRIGGER'; -export const panelHoverTrigger: Trigger = { - id: PANEL_HOVER_TRIGGER, - title: i18n.translate('presentationPanel.hoverTrigger.title', { - defaultMessage: 'Panel hover', - }), - description: i18n.translate('presentationPanel.hoverTrigger.description', { - defaultMessage: "A new action will be added to the panel's hover menu", - }), -}; - export const PANEL_BADGE_TRIGGER = 'PANEL_BADGE_TRIGGER'; export const panelBadgeTrigger: Trigger = { id: PANEL_BADGE_TRIGGER, diff --git a/src/platform/plugins/shared/charts/public/services/theme/theme.test.tsx b/src/platform/plugins/shared/charts/public/services/theme/theme.test.tsx index b478dc284d0d6..5c45da9472401 100644 --- a/src/platform/plugins/shared/charts/public/services/theme/theme.test.tsx +++ b/src/platform/plugins/shared/charts/public/services/theme/theme.test.tsx @@ -18,7 +18,7 @@ import { ThemeService } from './theme'; import { coreMock } from '@kbn/core/public/mocks'; const createTheme$Mock = (mode: boolean) => { - return from([{ darkMode: mode, name: 'amsterdam' }]); + return from([{ darkMode: mode, name: 'borealis' }]); }; const { theme: setUpMockTheme } = coreMock.createSetup(); @@ -36,7 +36,7 @@ describe('ThemeService', () => { expect(await themeService.darkModeEnabled$.pipe(take(1)).toPromise()).toStrictEqual({ darkMode: false, - name: 'amsterdam', + name: 'borealis', }); }); @@ -47,7 +47,7 @@ describe('ThemeService', () => { expect(await themeService.darkModeEnabled$.pipe(take(1)).toPromise()).toStrictEqual({ darkMode: true, - name: 'amsterdam', + name: 'borealis', }); }); }); diff --git a/src/platform/plugins/shared/console/public/application/containers/main/main.tsx b/src/platform/plugins/shared/console/public/application/containers/main/main.tsx index 9cc1300eea5fb..5a013a43d52cb 100644 --- a/src/platform/plugins/shared/console/public/application/containers/main/main.tsx +++ b/src/platform/plugins/shared/console/public/application/containers/main/main.tsx @@ -7,6 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ +import '../../../index.scss'; import React, { useEffect, useState } from 'react'; import { EuiFlexGroup, diff --git a/src/platform/plugins/shared/console/public/index.ts b/src/platform/plugins/shared/console/public/index.ts index f3abd73eaa2ed..4b60958b15bdd 100644 --- a/src/platform/plugins/shared/console/public/index.ts +++ b/src/platform/plugins/shared/console/public/index.ts @@ -7,7 +7,6 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import './index.scss'; import { PluginInitializerContext } from '@kbn/core/public'; import { ConsoleUIPlugin } from './plugin'; diff --git a/src/platform/plugins/shared/console/server/lib/proxy_request.test.ts b/src/platform/plugins/shared/console/server/lib/proxy_request.test.ts index 98068d84cd115..dd2b57d34f475 100644 --- a/src/platform/plugins/shared/console/server/lib/proxy_request.test.ts +++ b/src/platform/plugins/shared/console/server/lib/proxy_request.test.ts @@ -55,12 +55,18 @@ describe(`Console's send request`, () => { destroy: sinon.stub(), on() {}, once() {}, + protocol: 'http:', + host: 'nowhere.none', + method: 'POST', + path: '/_bulk', } as any; try { await sendProxyRequest({ timeout: 0 }); // immediately timeout fail('Should not reach here!'); } catch (e) { - expect(e.message).toEqual('Client request timeout'); + expect(e.message).toEqual( + 'Client request timeout for: http://nowhere.none with request POST /_bulk' + ); expect((fakeRequest.destroy as sinon.SinonStub).calledOnce).toBe(true); } }); diff --git a/src/platform/plugins/shared/console/server/lib/proxy_request.ts b/src/platform/plugins/shared/console/server/lib/proxy_request.ts index 9d083e4ff7af2..1459131ceabf2 100644 --- a/src/platform/plugins/shared/console/server/lib/proxy_request.ts +++ b/src/platform/plugins/shared/console/server/lib/proxy_request.ts @@ -55,12 +55,13 @@ export const proxyRequest = ({ finalUserHeaders.host = hostname; } + const parsedPort = port === '' ? undefined : parseInt(port, 10); const req = client.request({ method: method.toUpperCase(), // We support overriding this on a per request basis to support legacy proxy config. See ./proxy_config. rejectUnauthorized: typeof rejectUnauthorized === 'boolean' ? rejectUnauthorized : undefined, host: sanitizeHostname(hostname), - port: port === '' ? undefined : parseInt(port, 10), + port: parsedPort, protocol, path: `${pathname}${search || ''}`, headers: { @@ -96,7 +97,12 @@ export const proxyRequest = ({ req.destroy(); } if (!resolved) { - timeoutReject(Boom.gatewayTimeout('Client request timeout')); + const request = `${req.method} ${req.path}`; + const requestPath = `${req.protocol}//${req.host}${parsedPort ? `:${parsedPort}` : ''}`; + + timeoutReject( + Boom.gatewayTimeout(`Client request timeout for: ${requestPath} with request ${request}`) + ); } else { timeoutResolve(undefined); } diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/js/query/dsl.ts b/src/platform/plugins/shared/console/server/lib/spec_definitions/js/query/dsl.ts index 39cb4b89380ae..061ae74b3c2d9 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/js/query/dsl.ts +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/js/query/dsl.ts @@ -382,6 +382,35 @@ export const query = (specService: SpecDefinitionsService) => { _scope: '', query: {}, }, + knn: { + __template: { + field: '', + k: 10, + num_candidates: 100, + query_vector_builder: { + text_embedding: { + model_id: '', + model_text: '', + }, + }, + }, + field: '{field}', + filter: { __scope_link: 'GLOBAL.filter' }, + k: 10, + num_candidates: 100, + query_vector: [], + query_vector_builder: { + text_embedding: { + model_id: '', + model_text: '', + }, + }, + rescore_vector: { + oversample: 1.5, + }, + similarity: { __one_of: ['l2_norm', 'cosine', 'dot_product', 'max_inner_product'] }, + boost: 1.0, + }, match_all: { boost: 1, }, diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/js/search.ts b/src/platform/plugins/shared/console/server/lib/spec_definitions/js/search.ts index 503744e0fd9db..d643ce145eb03 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/js/search.ts +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/js/search.ts @@ -226,6 +226,12 @@ export const search = (specService: SpecDefinitionsService) => { knn: { __template: { field: '', + query_vector_builder: { + text_embedding: { + model_id: '', + model_text: '', + }, + }, k: 10, num_candidates: 100, }, @@ -236,9 +242,17 @@ export const search = (specService: SpecDefinitionsService) => { k: 10, num_candidates: 100, query_vector: [], - query_vector_builder: {}, - similarity: { __one_of: ['l2_norm', 'cosine', 'dot_product'] }, + query_vector_builder: { + text_embedding: { + model_id: '', + model_text: '', + }, + }, + similarity: { __one_of: ['l2_norm', 'cosine', 'dot_product', 'max_inner_product'] }, boost: 1.0, + rescore_vector: { + oversample: 1.5, + }, }, [ { @@ -248,8 +262,11 @@ export const search = (specService: SpecDefinitionsService) => { num_candidates: 100, query_vector: [], query_vector_builder: {}, - similarity: { __one_of: ['l2_norm', 'cosine', 'dot_product'] }, + similarity: { __one_of: ['l2_norm', 'cosine', 'dot_product', 'max_inner_product'] }, boost: 1.0, + rescore_vector: { + oversample: 1.5, + }, }, ], ], diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.aliases.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.aliases.json index b72c32624eee9..64b563029fa11 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.aliases.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.aliases.json @@ -6,11 +6,6 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", @@ -23,6 +18,11 @@ "closed", "hidden", "none" + ], + "master_timeout": [ + "30s", + "-1", + "0" ] }, "methods": [ diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.allocation.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.allocation.json index abb1a519f6ced..d4c14a432f576 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.allocation.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.allocation.json @@ -6,11 +6,6 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", @@ -25,7 +20,12 @@ "tb", "pb" ], - "local": "__flag__" + "local": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.component_templates.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.component_templates.json index 674cddc5b0404..509435c46843d 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.component_templates.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.component_templates.json @@ -6,18 +6,18 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", "filter_path": [], "human": "__flag__", "pretty": "__flag__", - "local": "__flag__" + "local": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.count.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.count.json index 84df20188febe..c2a3c11eba2dc 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.count.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.count.json @@ -6,11 +6,6 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.fielddata.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.fielddata.json index 3ddfd9a11e737..d4c94e98065f1 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.fielddata.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.fielddata.json @@ -6,11 +6,6 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.health.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.health.json index 25425707dca3e..70fc424eb8de1 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.health.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.health.json @@ -6,11 +6,6 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.help.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.help.json index bb880e0ddcad6..7e92520fa395e 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.help.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.help.json @@ -1,23 +1,5 @@ { "cat.help": { - "url_params": { - "format": [ - "text" - ], - "h": [], - "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], - "s": [], - "v": "__flag__", - "error_trace": "__flag__", - "filter_path": [], - "human": "__flag__", - "pretty": "__flag__" - }, "methods": [ "GET" ], diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.indices.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.indices.json index a9adaeb39531b..6d6eb559d4643 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.indices.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.indices.json @@ -6,11 +6,6 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", @@ -47,6 +42,11 @@ "m", "h", "d" + ], + "master_timeout": [ + "30s", + "-1", + "0" ] }, "methods": [ diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.master.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.master.json index ea542c8079dcd..9bc6dc8060cb0 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.master.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.master.json @@ -6,18 +6,18 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", "filter_path": [], "human": "__flag__", "pretty": "__flag__", - "local": "__flag__" + "local": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.ml_data_frame_analytics.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.ml_data_frame_analytics.json index 32a0e6ca8c4c2..b7c70f5e4f93f 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.ml_data_frame_analytics.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.ml_data_frame_analytics.json @@ -23,11 +23,6 @@ "version" ], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [ "assignment_explanation", "create_time", @@ -61,8 +56,13 @@ "pb" ], "time": [ - "-1", - "0" + "nanos", + "micros", + "ms", + "s", + "m", + "h", + "d" ] }, "methods": [ diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.ml_datafeeds.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.ml_datafeeds.json index 3250ac17cda8a..2440b4370ae4e 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.ml_datafeeds.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.ml_datafeeds.json @@ -19,11 +19,6 @@ "s" ], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [ "ae", "bc", diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.ml_jobs.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.ml_jobs.json index 568daa8e3c93f..6c042894fe8ae 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.ml_jobs.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.ml_jobs.json @@ -67,11 +67,6 @@ "state" ], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [ "assignment_explanation", "buckets.count", diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.ml_trained_models.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.ml_trained_models.json index 20f3984788634..09088c48d375f 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.ml_trained_models.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.ml_trained_models.json @@ -21,11 +21,6 @@ "version" ], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [ "create_time", "created_by", @@ -57,7 +52,16 @@ "pb" ], "from": "", - "size": "" + "size": "", + "time": [ + "nanos", + "micros", + "ms", + "s", + "m", + "h", + "d" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.nodeattrs.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.nodeattrs.json index 21cab800580fa..ce0bfb03ad1ff 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.nodeattrs.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.nodeattrs.json @@ -6,18 +6,18 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", "filter_path": [], "human": "__flag__", "pretty": "__flag__", - "local": "__flag__" + "local": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.nodes.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.nodes.json index f3b5af6e4b2df..de12ea97faa2f 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.nodes.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.nodes.json @@ -6,11 +6,6 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", @@ -26,7 +21,21 @@ "pb" ], "full_id": "__flag__", - "include_unloaded_segments": "__flag__" + "include_unloaded_segments": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], + "time": [ + "nanos", + "micros", + "ms", + "s", + "m", + "h", + "d" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.pending_tasks.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.pending_tasks.json index 65e66e3e55acf..3881a3283ce3e 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.pending_tasks.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.pending_tasks.json @@ -6,18 +6,27 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", "filter_path": [], "human": "__flag__", "pretty": "__flag__", - "local": "__flag__" + "local": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], + "time": [ + "nanos", + "micros", + "ms", + "s", + "m", + "h", + "d" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.plugins.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.plugins.json index ae1431e8c0201..8d4ee2338e4d8 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.plugins.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.plugins.json @@ -6,18 +6,19 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", "filter_path": [], "human": "__flag__", "pretty": "__flag__", - "local": "__flag__" + "include_bootstrap": "__flag__", + "local": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.recovery.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.recovery.json index 42ff670fb7235..fa4e71c9a6969 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.recovery.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.recovery.json @@ -6,11 +6,6 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", @@ -26,7 +21,16 @@ "tb", "pb" ], - "detailed": "__flag__" + "detailed": "__flag__", + "time": [ + "nanos", + "micros", + "ms", + "s", + "m", + "h", + "d" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.repositories.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.repositories.json index 37c8dda060d9b..75ec54f89a096 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.repositories.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.repositories.json @@ -6,17 +6,18 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "local": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.segments.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.segments.json index 20440023dfd28..5160ddd43819a 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.segments.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.segments.json @@ -6,11 +6,6 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", @@ -25,7 +20,12 @@ "tb", "pb" ], - "local": "__flag__" + "local": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.shards.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.shards.json index 04a57d279f469..5b4b85d31bb85 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.shards.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.shards.json @@ -6,11 +6,6 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", @@ -24,6 +19,20 @@ "gb", "tb", "pb" + ], + "master_timeout": [ + "30s", + "-1", + "0" + ], + "time": [ + "nanos", + "micros", + "ms", + "s", + "m", + "h", + "d" ] }, "methods": [ diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.snapshots.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.snapshots.json index 96c5df103996c..0b5468f892caa 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.snapshots.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.snapshots.json @@ -6,18 +6,27 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", "filter_path": [], "human": "__flag__", "pretty": "__flag__", - "ignore_unavailable": "__flag__" + "ignore_unavailable": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], + "time": [ + "nanos", + "micros", + "ms", + "s", + "m", + "h", + "d" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.tasks.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.tasks.json index f2f99ec25cf82..1e8800f4767cf 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.tasks.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.tasks.json @@ -6,11 +6,6 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", @@ -19,8 +14,23 @@ "pretty": "__flag__", "actions": "", "detailed": "__flag__", - "node_id": "", - "parent_task_id": "" + "nodes": "", + "parent_task_id": "", + "time": [ + "nanos", + "micros", + "ms", + "s", + "m", + "h", + "d" + ], + "timeout": [ + "30s", + "-1", + "0" + ], + "wait_for_completion": "__flag__" }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.templates.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.templates.json index 0688e65ff0d90..fb2013e43827c 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.templates.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.templates.json @@ -6,18 +6,18 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", "filter_path": [], "human": "__flag__", "pretty": "__flag__", - "local": "__flag__" + "local": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.thread_pool.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.thread_pool.json index ddb2a3893c3f9..a7adebb22b09c 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.thread_pool.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.thread_pool.json @@ -6,11 +6,6 @@ ], "h": [], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [], "v": "__flag__", "error_trace": "__flag__", @@ -26,7 +21,12 @@ "h", "d" ], - "local": "__flag__" + "local": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.transforms.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.transforms.json index d214f8536223f..105ac7c7e8dd7 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.transforms.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cat.transforms.json @@ -40,11 +40,6 @@ "version" ], "help": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "s": [ "changes_last_detection_time", "checkpoint", diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.delete_auto_follow_pattern.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.delete_auto_follow_pattern.json index 83b8b5745bf52..b9347be749d25 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.delete_auto_follow_pattern.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.delete_auto_follow_pattern.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "DELETE" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.follow.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.follow.json index 0b54616f468e7..252dbf45ec1c7 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.follow.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.follow.json @@ -5,6 +5,11 @@ "filter_path": [], "human": "__flag__", "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], "wait_for_active_shards": [ "all", "index-setting" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.follow_info.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.follow_info.json index abe4a15374c4d..1cd6bd9c1a651 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.follow_info.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.follow_info.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.follow_stats.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.follow_stats.json index 8b40599a7cb93..105066049b176 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.follow_stats.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.follow_stats.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.forget_follower.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.forget_follower.json index 4dcaae5c61661..adf6747309747 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.forget_follower.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.forget_follower.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "POST" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.get_auto_follow_pattern.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.get_auto_follow_pattern.json index 7c40ed85382d1..d96f6426f31d8 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.get_auto_follow_pattern.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.get_auto_follow_pattern.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.pause_auto_follow_pattern.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.pause_auto_follow_pattern.json index ec8dc922b562a..156959728dd1e 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.pause_auto_follow_pattern.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.pause_auto_follow_pattern.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "POST" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.pause_follow.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.pause_follow.json index 560f9739a6d30..9619f6b7f9f7d 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.pause_follow.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.pause_follow.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "POST" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.put_auto_follow_pattern.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.put_auto_follow_pattern.json index 0f142821d8eca..6a64f42741da4 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.put_auto_follow_pattern.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.put_auto_follow_pattern.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "PUT" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.resume_auto_follow_pattern.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.resume_auto_follow_pattern.json index f6c0cb41bde49..0fa7f5d15300f 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.resume_auto_follow_pattern.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.resume_auto_follow_pattern.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "POST" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.resume_follow.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.resume_follow.json index 4ca7160f05099..5de925ed0a862 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.resume_follow.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.resume_follow.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "POST" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.stats.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.stats.json index 4c287c1e2918d..29dae9737d726 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.stats.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.stats.json @@ -4,7 +4,17 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], + "timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.unfollow.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.unfollow.json index 80479e236eb1b..f42bc7ce379c8 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.unfollow.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ccr.unfollow.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "POST" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cluster.allocation_explain.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cluster.allocation_explain.json index 7f08550f1659e..654af816a886a 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cluster.allocation_explain.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cluster.allocation_explain.json @@ -6,7 +6,12 @@ "human": "__flag__", "pretty": "__flag__", "include_disk_info": "__flag__", - "include_yes_decisions": "__flag__" + "include_yes_decisions": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET", diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cluster.delete_voting_config_exclusions.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cluster.delete_voting_config_exclusions.json index e1fe9c5180127..009eea0adaa25 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cluster.delete_voting_config_exclusions.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cluster.delete_voting_config_exclusions.json @@ -5,6 +5,11 @@ "filter_path": [], "human": "__flag__", "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], "wait_for_removal": "__flag__" }, "methods": [ diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cluster.post_voting_config_exclusions.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cluster.post_voting_config_exclusions.json index 9221716f4944e..c2ccf2b334e0e 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cluster.post_voting_config_exclusions.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/cluster.post_voting_config_exclusions.json @@ -7,6 +7,11 @@ "pretty": "__flag__", "node_names": [], "node_ids": [], + "master_timeout": [ + "30s", + "-1", + "0" + ], "timeout": [ "30s", "-1", diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.sync_job_check_in.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.sync_job_check_in.json index 54be708a6e7fe..5e4779870c855 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.sync_job_check_in.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.sync_job_check_in.json @@ -1,12 +1,18 @@ { "connector.sync_job_check_in": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__" + }, "methods": [ "PUT" ], "patterns": [ "_connector/_sync_job/{connector_sync_job_id}/_check_in" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/check-in-connector-sync-job-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/check-in-connector-sync-job-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.sync_job_claim.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.sync_job_claim.json index 7abe3c845a22d..00b71874fd416 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.sync_job_claim.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.sync_job_claim.json @@ -1,12 +1,18 @@ { "connector.sync_job_claim": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__" + }, "methods": [ "PUT" ], "patterns": [ "_connector/_sync_job/{connector_sync_job_id}/_claim" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/claim-connector-sync-job-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/claim-connector-sync-job-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.sync_job_error.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.sync_job_error.json index c312d25bfb3ac..a292f0c60bbd3 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.sync_job_error.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.sync_job_error.json @@ -1,12 +1,18 @@ { "connector.sync_job_error": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__" + }, "methods": [ "PUT" ], "patterns": [ "_connector/_sync_job/{connector_sync_job_id}/_error" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/set-connector-sync-job-error-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/set-connector-sync-job-error-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.sync_job_update_stats.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.sync_job_update_stats.json index f6b09c8a5b658..756b8ad2efbe8 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.sync_job_update_stats.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.sync_job_update_stats.json @@ -1,12 +1,18 @@ { "connector.sync_job_update_stats": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__" + }, "methods": [ "PUT" ], "patterns": [ "_connector/_sync_job/{connector_sync_job_id}/_stats" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/set-connector-sync-job-stats-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/set-connector-sync-job-stats-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.update_features.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.update_features.json index fd9ef3fbcced0..4f03d4105ad4d 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.update_features.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/connector.update_features.json @@ -1,12 +1,18 @@ { "connector.update_features": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__" + }, "methods": [ "PUT" ], "patterns": [ "_connector/{connector_id}/_features" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/update-connector-features-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/update-connector-features-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/dangling_indices.delete_dangling_index.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/dangling_indices.delete_dangling_index.json index ac6c1edb598fa..b267e5560cfda 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/dangling_indices.delete_dangling_index.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/dangling_indices.delete_dangling_index.json @@ -21,7 +21,7 @@ "patterns": [ "_dangling/{index_uuid}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-gateway-dangling-indices.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/dangling-index-delete.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/dangling_indices.import_dangling_index.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/dangling_indices.import_dangling_index.json index 2e5281d432b92..dfbd42b22e86a 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/dangling_indices.import_dangling_index.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/dangling_indices.import_dangling_index.json @@ -21,7 +21,7 @@ "patterns": [ "_dangling/{index_uuid}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-gateway-dangling-indices.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/dangling-index-import.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/dangling_indices.list_dangling_indices.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/dangling_indices.list_dangling_indices.json index 24614b377256f..af996b21e5060 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/dangling_indices.list_dangling_indices.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/dangling_indices.list_dangling_indices.json @@ -12,7 +12,7 @@ "patterns": [ "_dangling" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-gateway-dangling-indices.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/dangling-indices-list.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.delete_policy.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.delete_policy.json index d0b4e25406f67..59a8a57194f42 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.delete_policy.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.delete_policy.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "DELETE" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.execute_policy.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.execute_policy.json index c9b5e560543c0..e55035166f5ab 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.execute_policy.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.execute_policy.json @@ -5,6 +5,11 @@ "filter_path": [], "human": "__flag__", "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], "wait_for_completion": "__flag__" }, "methods": [ diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.get_policy.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.get_policy.json index 80777d53b8f5e..67e978c6c3413 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.get_policy.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.get_policy.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.put_policy.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.put_policy.json index 5a7fbb10f6ca9..3646b8035c864 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.put_policy.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.put_policy.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "PUT" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.stats.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.stats.json index e91905ea607b0..2c3bcc6638a63 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.stats.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/enrich.stats.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/eql.search.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/eql.search.json index 77cd26f4989ab..2275ebf0dc3d6 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/eql.search.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/eql.search.json @@ -6,6 +6,8 @@ "human": "__flag__", "pretty": "__flag__", "allow_no_indices": "__flag__", + "allow_partial_search_results": "__flag__", + "allow_partial_sequence_results": "__flag__", "expand_wildcards": [ "all", "open", diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/features.get_features.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/features.get_features.json index 367e3b5af0431..2cdc490524754 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/features.get_features.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/features.get_features.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/features.reset_features.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/features.reset_features.json index 7c5886e3a53cd..de73b903c4e5d 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/features.reset_features.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/features.reset_features.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "POST" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ilm.explain_lifecycle.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ilm.explain_lifecycle.json index 10fc47f7b76a0..f66f90c096915 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ilm.explain_lifecycle.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ilm.explain_lifecycle.json @@ -11,11 +11,6 @@ "30s", "-1", "0" - ], - "timeout": [ - "30s", - "-1", - "0" ] }, "methods": [ diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ilm.start.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ilm.start.json index 8aaf75a55e638..53b4668717267 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ilm.start.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ilm.start.json @@ -6,10 +6,12 @@ "human": "__flag__", "pretty": "__flag__", "master_timeout": [ + "30s", "-1", "0" ], "timeout": [ + "30s", "-1", "0" ] diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ilm.stop.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ilm.stop.json index 96834bf9bd87e..b73a8c3756085 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ilm.stop.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ilm.stop.json @@ -6,10 +6,12 @@ "human": "__flag__", "pretty": "__flag__", "master_timeout": [ + "30s", "-1", "0" ], "timeout": [ + "30s", "-1", "0" ] diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.delete.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.delete.json index 845b9e60b861e..f2e04d8863d1a 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.delete.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.delete.json @@ -31,7 +31,7 @@ "patterns": [ "{index}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-delete-index.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-delete-index.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.delete_alias.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.delete_alias.json index fdff5139506fd..8741260f97314 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.delete_alias.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.delete_alias.json @@ -23,7 +23,7 @@ "{index}/_alias/{name}", "{index}/_aliases/{name}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-aliases.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-delete-alias.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.delete_index_template.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.delete_index_template.json index 8144a6adbc8a0..62022dc9b3ea3 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.delete_index_template.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.delete_index_template.json @@ -22,7 +22,7 @@ "patterns": [ "_index_template/{name}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-delete-template.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-delete-template.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.delete_template.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.delete_template.json index 97f2be6b72999..2c4d5f52f6993 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.delete_template.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.delete_template.json @@ -22,7 +22,7 @@ "patterns": [ "_template/{name}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-delete-template-v1.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-delete-template-v1.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.exists.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.exists.json index bf618abaad72f..23e8d64d3a95a 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.exists.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.exists.json @@ -24,7 +24,7 @@ "patterns": [ "{index}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-exists.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-exists.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.exists_template.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.exists_template.json index 4089c0f8b6a36..b0b9f4415bfe7 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.exists_template.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.exists_template.json @@ -8,6 +8,7 @@ "flat_settings": "__flag__", "local": "__flag__", "master_timeout": [ + "30s", "-1", "0" ] @@ -18,7 +19,7 @@ "patterns": [ "_template/{name}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-template-exists-v1.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-template-exists-v1.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.field_usage_stats.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.field_usage_stats.json index fbe1263e392f1..16c37268fb0a3 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.field_usage_stats.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.field_usage_stats.json @@ -15,16 +15,6 @@ ], "ignore_unavailable": "__flag__", "fields": [], - "master_timeout": [ - "30s", - "-1", - "0" - ], - "timeout": [ - "30s", - "-1", - "0" - ], "wait_for_active_shards": [ "1", "all", @@ -37,7 +27,7 @@ "patterns": [ "{index}/_field_usage_stats" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/field-usage-stats.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/field-usage-stats.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.forcemerge.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.forcemerge.json index 1c126eea73478..1de8af0fa874a 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.forcemerge.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.forcemerge.json @@ -26,7 +26,7 @@ "_forcemerge", "{index}/_forcemerge" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-forcemerge.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-forcemerge.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get.json index f556873352164..5933646b05d86 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get.json @@ -34,7 +34,7 @@ "patterns": [ "{index}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-index.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-get-index.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_alias.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_alias.json index 236cd8b363c7e..fcbe1827da140 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_alias.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_alias.json @@ -29,7 +29,7 @@ "{index}/_alias/{name}", "{index}/_alias" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-aliases.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-get-alias.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_data_lifecycle_stats.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_data_lifecycle_stats.json new file mode 100644 index 0000000000000..4dac2621067be --- /dev/null +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_data_lifecycle_stats.json @@ -0,0 +1,21 @@ +{ + "indices.get_data_lifecycle_stats": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_lifecycle/stats" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/data-streams-get-lifecycle-stats.html", + "availability": { + "stack": true, + "serverless": false + } + } +} diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_field_mapping.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_field_mapping.json index e48bc4525a3ce..0ea15837eb2d3 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_field_mapping.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_field_mapping.json @@ -24,7 +24,7 @@ "_mapping/field/{fields}", "{index}/_mapping/field/{fields}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-field-mapping.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-get-field-mapping.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_index_template.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_index_template.json index 18f1cdf510134..5812bc5119766 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_index_template.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_index_template.json @@ -21,7 +21,7 @@ "_index_template", "_index_template/{name}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-template.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-get-template.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_mapping.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_mapping.json index 46c2425b1ceb8..353d0ba0d0f7e 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_mapping.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_mapping.json @@ -28,7 +28,7 @@ "_mapping", "{index}/_mapping" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-mapping.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-get-mapping.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_settings.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_settings.json index 3bbf55f534e34..f0b788762b454 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_settings.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_settings.json @@ -32,7 +32,7 @@ "{index}/_settings/{name}", "_settings/{name}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-settings.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-get-settings.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_template.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_template.json index d257e18b62af4..64e46fbea3020 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_template.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.get_template.json @@ -20,7 +20,7 @@ "_template", "_template/{name}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-template-v1.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-get-template-v1.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.open.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.open.json index 0125fc7f4d729..89bded387b8f9 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.open.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.open.json @@ -36,7 +36,7 @@ "patterns": [ "{index}/_open" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-open-close.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-open-close.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.put_mapping.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.put_mapping.json index f9c661b283e3c..3b28f84d475dc 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.put_mapping.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.put_mapping.json @@ -33,7 +33,7 @@ "patterns": [ "{index}/_mapping" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-put-mapping.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-put-mapping.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.put_settings.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.put_settings.json index 828fe4e5ab621..b77c7d9bead52 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.put_settings.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.put_settings.json @@ -34,7 +34,7 @@ "_settings", "{index}/_settings" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-update-settings.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-update-settings.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.put_template.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.put_template.json index 4ad03e50b1791..5b7884caf5b93 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.put_template.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.put_template.json @@ -21,7 +21,7 @@ "patterns": [ "_template/{name}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-templates-v1.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-templates-v1.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.recovery.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.recovery.json index 001553a2b41d9..74f129e5f0e4f 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.recovery.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.recovery.json @@ -15,7 +15,7 @@ "_recovery", "{index}/_recovery" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-recovery.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-recovery.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.refresh.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.refresh.json index 8e631a9a4b567..ff6925fbbd018 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.refresh.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.refresh.json @@ -23,7 +23,7 @@ "_refresh", "{index}/_refresh" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-refresh.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-refresh.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.reload_search_analyzers.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.reload_search_analyzers.json index da5e63aecb7ea..1e396faaa2caa 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.reload_search_analyzers.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.reload_search_analyzers.json @@ -22,7 +22,7 @@ "patterns": [ "{index}/_reload_search_analyzers" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-reload-analyzers.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-reload-analyzers.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.resolve_cluster.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.resolve_cluster.json index 41344e43df884..49341ccae8b8d 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.resolve_cluster.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.resolve_cluster.json @@ -22,7 +22,7 @@ "patterns": [ "_resolve/cluster/{name}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-resolve-cluster-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-resolve-cluster-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.resolve_index.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.resolve_index.json index 790e5ecd171f1..5f1c37f0573b3 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.resolve_index.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.resolve_index.json @@ -21,7 +21,7 @@ "patterns": [ "_resolve/index/{name}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-resolve-index-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-resolve-index-api.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.segments.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.segments.json index be2ffc744e7a0..ff06a4d6f456e 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.segments.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.segments.json @@ -22,7 +22,7 @@ "_segments", "{index}/_segments" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-segments.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-segments.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.shard_stores.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.shard_stores.json index 3d64c11b6ab53..c706fec1b61e2 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.shard_stores.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.shard_stores.json @@ -28,7 +28,7 @@ "_shard_stores", "{index}/_shard_stores" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-shards-stores.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-shards-stores.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.simulate_index_template.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.simulate_index_template.json index 8c4cae8e6ddc5..b5123e07e15e5 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.simulate_index_template.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.simulate_index_template.json @@ -18,7 +18,7 @@ "patterns": [ "_index_template/_simulate_index/{name}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-simulate-index.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-simulate-index.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.simulate_template.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.simulate_template.json index d19188cbd4c41..a3201c14cd64b 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.simulate_template.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.simulate_template.json @@ -20,7 +20,7 @@ "_index_template/_simulate", "_index_template/_simulate/{name}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-simulate-template.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-simulate-template.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.stats.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.stats.json index 84bac12732b62..9823d3bc7b095 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.stats.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.stats.json @@ -34,7 +34,7 @@ "{index}/_stats", "{index}/_stats/{metric}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-stats.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/indices-stats.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.unfreeze.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.unfreeze.json index 9b9789d3d9772..a8b852f4389ef 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.unfreeze.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/indices.unfreeze.json @@ -34,7 +34,7 @@ "patterns": [ "{index}/_unfreeze" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/unfreeze-index-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/unfreeze-index-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/info.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/info.json index 9ac0e521ba9c5..235043c916674 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/info.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/info.json @@ -12,7 +12,7 @@ "patterns": [ "" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/rest-api-root.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ingest.delete_ip_location_database.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ingest.delete_ip_location_database.json index c5008f8e7b9ac..aad18dca11867 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ingest.delete_ip_location_database.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ingest.delete_ip_location_database.json @@ -1,5 +1,21 @@ { "ingest.delete_ip_location_database": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], + "timeout": [ + "30s", + "-1", + "0" + ] + }, "methods": [ "DELETE" ], diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ingest.get_geoip_database.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ingest.get_geoip_database.json index e57b36f09cbf7..648335792ce07 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ingest.get_geoip_database.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ingest.get_geoip_database.json @@ -4,12 +4,7 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ] + "pretty": "__flag__" }, "methods": [ "GET" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ingest.get_ip_location_database.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ingest.get_ip_location_database.json index bcdce161cbdf1..8a7a8945afb07 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ingest.get_ip_location_database.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ingest.get_ip_location_database.json @@ -1,5 +1,16 @@ { "ingest.get_ip_location_database": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] + }, "methods": [ "GET" ], diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ingest.put_ip_location_database.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ingest.put_ip_location_database.json index 93ab93da54972..b13578fb315b8 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ingest.put_ip_location_database.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ingest.put_ip_location_database.json @@ -1,5 +1,21 @@ { "ingest.put_ip_location_database": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], + "timeout": [ + "30s", + "-1", + "0" + ] + }, "methods": [ "PUT" ], diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/license.delete.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/license.delete.json index 8bc6a567eca73..ce9e0d5312c68 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/license.delete.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/license.delete.json @@ -4,7 +4,17 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], + "timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "DELETE" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/license.post.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/license.post.json index d821aa66ef02b..e636442ebb9b2 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/license.post.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/license.post.json @@ -5,7 +5,17 @@ "filter_path": [], "human": "__flag__", "pretty": "__flag__", - "acknowledge": "__flag__" + "acknowledge": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], + "timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "PUT", diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/license.post_start_basic.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/license.post_start_basic.json index 3621e8f34c791..ed7caed78d2fe 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/license.post_start_basic.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/license.post_start_basic.json @@ -5,7 +5,17 @@ "filter_path": [], "human": "__flag__", "pretty": "__flag__", - "acknowledge": "__flag__" + "acknowledge": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], + "timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "POST" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/license.post_start_trial.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/license.post_start_trial.json index 33ed6e1c59cf7..6f14c870c99cb 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/license.post_start_trial.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/license.post_start_trial.json @@ -6,7 +6,12 @@ "human": "__flag__", "pretty": "__flag__", "acknowledge": "__flag__", - "type_query_string": "" + "type_query_string": "", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "POST" @@ -14,7 +19,7 @@ "patterns": [ "_license/start_trial" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/start-trial.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/start-trial.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/logstash.delete_pipeline.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/logstash.delete_pipeline.json index 62c30e5d5879a..ac85f4a48032b 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/logstash.delete_pipeline.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/logstash.delete_pipeline.json @@ -12,7 +12,7 @@ "patterns": [ "_logstash/pipeline/{id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/logstash-api-delete-pipeline.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/logstash-api-delete-pipeline.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/logstash.get_pipeline.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/logstash.get_pipeline.json index 674de6e2bffe5..5f457aebf9598 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/logstash.get_pipeline.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/logstash.get_pipeline.json @@ -13,7 +13,7 @@ "_logstash/pipeline", "_logstash/pipeline/{id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/logstash-api-get-pipeline.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/logstash-api-get-pipeline.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/logstash.put_pipeline.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/logstash.put_pipeline.json index 280627516ccbf..a5d6e726bb044 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/logstash.put_pipeline.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/logstash.put_pipeline.json @@ -12,7 +12,7 @@ "patterns": [ "_logstash/pipeline/{id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/logstash-api-put-pipeline.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/logstash-api-put-pipeline.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/migration.deprecations.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/migration.deprecations.json index 9fe5235e31738..1b09911c6a405 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/migration.deprecations.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/migration.deprecations.json @@ -13,7 +13,7 @@ "_migration/deprecations", "{index}/_migration/deprecations" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/migration-api-deprecation.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/migration-api-deprecation.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/migration.get_feature_upgrade_status.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/migration.get_feature_upgrade_status.json index 58774c1c1ef5a..cd07f477ee04b 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/migration.get_feature_upgrade_status.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/migration.get_feature_upgrade_status.json @@ -12,7 +12,7 @@ "patterns": [ "_migration/system_features" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/migration-api-feature-upgrade.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/feature-migration-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/migration.post_feature_upgrade.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/migration.post_feature_upgrade.json index e7ae097da9650..629af9a98b623 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/migration.post_feature_upgrade.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/migration.post_feature_upgrade.json @@ -12,7 +12,7 @@ "patterns": [ "_migration/system_features" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/migration-api-feature-upgrade.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/feature-migration-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ml.delete_trained_model.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ml.delete_trained_model.json index 05e9b42e2bded..f7981ad4b93cd 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ml.delete_trained_model.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/ml.delete_trained_model.json @@ -5,7 +5,12 @@ "filter_path": [], "human": "__flag__", "pretty": "__flag__", - "force": "__flag__" + "force": "__flag__", + "timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "DELETE" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/monitoring.bulk.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/monitoring.bulk.json index 2b1bec6fb4c54..414a6d7b7d1ca 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/monitoring.bulk.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/monitoring.bulk.json @@ -22,7 +22,7 @@ ], "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/monitor-elasticsearch-cluster.html", "availability": { - "stack": true, + "stack": false, "serverless": false } } diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.clear_repositories_metering_archive.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.clear_repositories_metering_archive.json index f0135ed3fd39c..89bb9430661df 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.clear_repositories_metering_archive.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.clear_repositories_metering_archive.json @@ -12,7 +12,7 @@ "patterns": [ "_nodes/{node_id}/_repositories_metering/{max_archive_version}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/clear-repositories-metering-archive-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/clear-repositories-metering-archive-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.get_repositories_metering_info.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.get_repositories_metering_info.json index e1bd76a6cd60f..9cbcf37a64ae1 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.get_repositories_metering_info.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.get_repositories_metering_info.json @@ -12,7 +12,7 @@ "patterns": [ "_nodes/{node_id}/_repositories_metering" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/get-repositories-metering-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/get-repositories-metering-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.hot_threads.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.hot_threads.json index bde9f886b5383..c64bda9f90700 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.hot_threads.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.hot_threads.json @@ -14,11 +14,6 @@ "snapshots": [ "10" ], - "master_timeout": [ - "30s", - "-1", - "0" - ], "threads": [ "3" ], diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.info.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.info.json index b32e79cb89066..94e4d901a2846 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.info.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.info.json @@ -6,11 +6,6 @@ "human": "__flag__", "pretty": "__flag__", "flat_settings": "__flag__", - "master_timeout": [ - "30s", - "-1", - "0" - ], "timeout": [ "30s", "-1", diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.stats.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.stats.json index b3d7abda297fe..8ce7e1e44bf5c 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.stats.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/nodes.stats.json @@ -15,11 +15,6 @@ "indices", "shards" ], - "master_timeout": [ - "30s", - "-1", - "0" - ], "timeout": [ "30s", "-1", diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.delete_rule.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.delete_rule.json index 4255ae1672064..e887721673162 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.delete_rule.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.delete_rule.json @@ -12,7 +12,7 @@ "patterns": [ "_query_rules/{ruleset_id}/_rule/{rule_id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/delete-query-rule.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/delete-query-rule.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.delete_ruleset.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.delete_ruleset.json index d4f34e7d76716..3ee857c048d85 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.delete_ruleset.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.delete_ruleset.json @@ -12,7 +12,7 @@ "patterns": [ "_query_rules/{ruleset_id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/delete-query-ruleset.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/delete-query-ruleset.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.get_rule.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.get_rule.json index fdd424c2a2d1b..0dced0c1d3a4e 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.get_rule.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.get_rule.json @@ -12,7 +12,7 @@ "patterns": [ "_query_rules/{ruleset_id}/_rule/{rule_id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/get-query-rule.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/get-query-rule.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.get_ruleset.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.get_ruleset.json index 23cff910d815e..4b271ce3a0d5e 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.get_ruleset.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.get_ruleset.json @@ -12,7 +12,7 @@ "patterns": [ "_query_rules/{ruleset_id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/get-query-ruleset.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/get-query-ruleset.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.list_rulesets.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.list_rulesets.json index c20f8050c5c91..940a4f774a4d6 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.list_rulesets.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.list_rulesets.json @@ -14,7 +14,7 @@ "patterns": [ "_query_rules" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/list-query-rulesets.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/list-query-rulesets.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.put_rule.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.put_rule.json index 2653a15dab650..d3f5b67dfe207 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.put_rule.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.put_rule.json @@ -12,7 +12,7 @@ "patterns": [ "_query_rules/{ruleset_id}/_rule/{rule_id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/put-query-rule.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/put-query-rule.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.put_ruleset.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.put_ruleset.json index a4c0ad3c72d94..8f94c9cee71a7 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.put_ruleset.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.put_ruleset.json @@ -12,7 +12,7 @@ "patterns": [ "_query_rules/{ruleset_id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/put-query-ruleset.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/put-query-ruleset.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.test.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.test.json index 9b603e23818ac..23309cd60365c 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.test.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/query_rules.test.json @@ -12,7 +12,7 @@ "patterns": [ "_query_rules/{ruleset_id}/_test" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/test-query-ruleset.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/test-query-ruleset.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.delete_job.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.delete_job.json index d8e44fd3ed5c9..9e8ebfa6c3452 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.delete_job.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.delete_job.json @@ -12,7 +12,7 @@ "patterns": [ "_rollup/job/{id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/rollup-delete-job.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/rollup-delete-job.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.get_jobs.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.get_jobs.json index a4bf785822c3b..74e02c025250f 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.get_jobs.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.get_jobs.json @@ -13,7 +13,7 @@ "_rollup/job/{id}", "_rollup/job" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/rollup-get-job.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/rollup-get-job.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.get_rollup_caps.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.get_rollup_caps.json index f3b50f92312d1..4649ddb0735da 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.get_rollup_caps.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.get_rollup_caps.json @@ -13,7 +13,7 @@ "_rollup/data/{id}", "_rollup/data" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/rollup-get-rollup-caps.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/rollup-get-rollup-caps.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.get_rollup_index_caps.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.get_rollup_index_caps.json index e6999b91eda6a..e7a9680e16a79 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.get_rollup_index_caps.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.get_rollup_index_caps.json @@ -12,7 +12,7 @@ "patterns": [ "{index}/_rollup/data" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/rollup-get-rollup-index-caps.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/rollup-get-rollup-index-caps.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.put_job.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.put_job.json index 0a7841cf199ba..acce461adddbf 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.put_job.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.put_job.json @@ -12,7 +12,7 @@ "patterns": [ "_rollup/job/{id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/rollup-put-job.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/rollup-put-job.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.rollup_search.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.rollup_search.json index 7db62d712066c..25eac8113c7e9 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.rollup_search.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.rollup_search.json @@ -15,7 +15,7 @@ "patterns": [ "{index}/_rollup_search" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/rollup-search.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/rollup-search.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.start_job.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.start_job.json index da3c94de904b7..4459962f0903b 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.start_job.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.start_job.json @@ -12,7 +12,7 @@ "patterns": [ "_rollup/job/{id}/_start" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/rollup-start-job.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/rollup-start-job.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.stop_job.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.stop_job.json index ecdb9372b22e8..0938a9da559c4 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.stop_job.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/rollup.stop_job.json @@ -18,7 +18,7 @@ "patterns": [ "_rollup/job/{id}/_stop" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/rollup-stop-job.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/rollup-stop-job.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/search_application.post_behavioral_analytics_event.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/search_application.post_behavioral_analytics_event.json index 983421e2e30d2..e08199c4c18df 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/search_application.post_behavioral_analytics_event.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/search_application.post_behavioral_analytics_event.json @@ -1,12 +1,26 @@ { "search_application.post_behavioral_analytics_event": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__", + "debug": "__flag__" + }, + "url_components": { + "event_type": [ + "page_view", + "search", + "search_click" + ] + }, "methods": [ "POST" ], "patterns": [ "_application/analytics/{collection_name}/event/{event_type}" ], - "documentation": "http://todo.com/tbd", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/post-analytics-collection-event.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/search_application.render_query.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/search_application.render_query.json index 68288f6bc0f6e..e2f607cdf52c0 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/search_application.render_query.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/search_application.render_query.json @@ -1,12 +1,18 @@ { "search_application.render_query": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__" + }, "methods": [ "POST" ], "patterns": [ "_application/search_application/{name}/_render_query" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-application-render-query.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/search-application-render-query.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/search_shards.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/search_shards.json index 93bb86abe387b..ccc8dd653d0b6 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/search_shards.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/search_shards.json @@ -15,6 +15,11 @@ ], "ignore_unavailable": "__flag__", "local": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], "preference": "", "routing": "" }, diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/searchable_snapshots.cache_stats.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/searchable_snapshots.cache_stats.json index b28c45baad38c..79443dd2ead35 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/searchable_snapshots.cache_stats.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/searchable_snapshots.cache_stats.json @@ -17,7 +17,7 @@ "_searchable_snapshots/cache/stats", "_searchable_snapshots/{node_id}/cache/stats" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/searchable-snapshots-apis.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/searchable-snapshots-api-cache-stats.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/searchable_snapshots.clear_cache.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/searchable_snapshots.clear_cache.json index e1a46ac66e279..1705e5f5b2da1 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/searchable_snapshots.clear_cache.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/searchable_snapshots.clear_cache.json @@ -22,7 +22,7 @@ "_searchable_snapshots/cache/clear", "{index}/_searchable_snapshots/cache/clear" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/searchable-snapshots-apis.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/searchable-snapshots-api-clear-cache.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/searchable_snapshots.mount.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/searchable_snapshots.mount.json index f5392588762ba..3812410af9540 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/searchable_snapshots.mount.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/searchable_snapshots.mount.json @@ -21,7 +21,7 @@ "patterns": [ "_snapshot/{repository}/{snapshot}/_mount" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/searchable-snapshots-api-mount-snapshot.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/searchable-snapshots-api-mount-snapshot.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/searchable_snapshots.stats.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/searchable_snapshots.stats.json index 05c40d652d556..5caa5c8df07cb 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/searchable_snapshots.stats.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/searchable_snapshots.stats.json @@ -18,7 +18,7 @@ "_searchable_snapshots/stats", "{index}/_searchable_snapshots/stats" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/searchable-snapshots-apis.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/searchable-snapshots-api-stats.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.bulk_update_api_keys.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.bulk_update_api_keys.json index 6895efb587994..a9ad1fe4d2f5f 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.bulk_update_api_keys.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.bulk_update_api_keys.json @@ -1,12 +1,18 @@ { "security.bulk_update_api_keys": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__" + }, "methods": [ "POST" ], "patterns": [ "_security/api_key/_bulk_update" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-bulk-update-api-keys.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/security-api-bulk-update-api-keys.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.delegate_pki.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.delegate_pki.json new file mode 100644 index 0000000000000..43e76eaa43d49 --- /dev/null +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.delegate_pki.json @@ -0,0 +1,21 @@ +{ + "security.delegate_pki": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__" + }, + "methods": [ + "POST" + ], + "patterns": [ + "_security/delegate_pki" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/security-api-delegate-pki-authentication.html", + "availability": { + "stack": true, + "serverless": false + } + } +} diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.get_settings.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.get_settings.json index f91793b92cc8c..80d8446870f54 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.get_settings.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.get_settings.json @@ -1,12 +1,22 @@ { "security.get_settings": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__", + "master_timeout": [ + "-1", + "0" + ] + }, "methods": [ "GET" ], "patterns": [ "_security/settings" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-get-settings.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/security-api-get-settings.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.oidc_authenticate.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.oidc_authenticate.json index cd53074297666..51ba54d283404 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.oidc_authenticate.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.oidc_authenticate.json @@ -1,12 +1,18 @@ { "security.oidc_authenticate": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__" + }, "methods": [ "POST" ], "patterns": [ "_security/oidc/authenticate" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-oidc-authenticate.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/security-api-oidc-authenticate.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.oidc_logout.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.oidc_logout.json index 3353df757121d..d9a12c78857b9 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.oidc_logout.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.oidc_logout.json @@ -1,12 +1,18 @@ { "security.oidc_logout": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__" + }, "methods": [ "POST" ], "patterns": [ "_security/oidc/logout" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-oidc-logout.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/security-api-oidc-logout.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.oidc_prepare_authentication.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.oidc_prepare_authentication.json index 372af153b6954..e63ad0bee3bab 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.oidc_prepare_authentication.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.oidc_prepare_authentication.json @@ -1,12 +1,18 @@ { "security.oidc_prepare_authentication": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__" + }, "methods": [ "POST" ], "patterns": [ "_security/oidc/prepare" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-oidc-prepare-authentication.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/security-api-oidc-prepare-authentication.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.query_role.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.query_role.json index 7648662f973c0..7ad1224ceafd7 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.query_role.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.query_role.json @@ -16,7 +16,7 @@ "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-query-role.html", "availability": { "stack": true, - "serverless": false + "serverless": true } } } diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.update_settings.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.update_settings.json index 609adc164cc0f..c8b5dbddfe959 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.update_settings.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/security.update_settings.json @@ -1,12 +1,26 @@ { "security.update_settings": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__", + "master_timeout": [ + "-1", + "0" + ], + "timeout": [ + "-1", + "0" + ] + }, "methods": [ "PUT" ], "patterns": [ "_security/settings" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-update-settings.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/security-api-update-settings.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/shutdown.delete_node.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/shutdown.delete_node.json index 692822e2dadc4..545454cddd961 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/shutdown.delete_node.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/shutdown.delete_node.json @@ -30,7 +30,7 @@ "patterns": [ "_nodes/{node_id}/shutdown" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/delete-shutdown.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/shutdown.get_node.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/shutdown.get_node.json index 287bda52097cd..17f3de6d339d5 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/shutdown.get_node.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/shutdown.get_node.json @@ -13,15 +13,6 @@ "m", "h", "d" - ], - "timeout": [ - "nanos", - "micros", - "ms", - "s", - "m", - "h", - "d" ] }, "methods": [ @@ -31,7 +22,7 @@ "_nodes/shutdown", "_nodes/{node_id}/shutdown" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/get-shutdown.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/shutdown.put_node.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/shutdown.put_node.json index a2985683a48a9..e9b9abd83cbac 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/shutdown.put_node.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/shutdown.put_node.json @@ -30,7 +30,7 @@ "patterns": [ "_nodes/{node_id}/shutdown" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/put-shutdown.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/simulate.ingest.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/simulate.ingest.json index 9f7c9a4e91b3d..015680b28c75d 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/simulate.ingest.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/simulate.ingest.json @@ -1,5 +1,12 @@ { "simulate.ingest": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__", + "pipeline": "" + }, "methods": [ "GET", "POST" @@ -8,7 +15,7 @@ "_ingest/_simulate", "_ingest/{index}/_simulate" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/simulate-ingest-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/simulate-ingest-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.delete_lifecycle.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.delete_lifecycle.json index f6ecb9163f7e7..d9a8de1b741bb 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.delete_lifecycle.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.delete_lifecycle.json @@ -4,7 +4,17 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], + "timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "DELETE" @@ -12,7 +22,7 @@ "patterns": [ "_slm/policy/{policy_id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-delete-policy.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/slm-api-delete-policy.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.execute_lifecycle.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.execute_lifecycle.json index 0b3cc87935e37..9601872e3e6fd 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.execute_lifecycle.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.execute_lifecycle.json @@ -4,7 +4,17 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], + "timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "PUT" @@ -12,7 +22,7 @@ "patterns": [ "_slm/policy/{policy_id}/_execute" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-execute-lifecycle.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/slm-api-execute-lifecycle.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.execute_retention.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.execute_retention.json index 0938026354237..71c1f06dc7fea 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.execute_retention.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.execute_retention.json @@ -4,7 +4,17 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], + "timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "POST" @@ -12,7 +22,7 @@ "patterns": [ "_slm/_execute_retention" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-execute-retention.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/slm-api-execute-retention.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.get_lifecycle.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.get_lifecycle.json index a2b3b8300314f..ab9e513bb7c61 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.get_lifecycle.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.get_lifecycle.json @@ -4,7 +4,17 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], + "timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" @@ -13,7 +23,7 @@ "_slm/policy/{policy_id}", "_slm/policy" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-get-policy.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/slm-api-get-policy.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.get_stats.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.get_stats.json index 10789aa3934fe..b7776219f5a1d 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.get_stats.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.get_stats.json @@ -4,7 +4,17 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], + "timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" @@ -12,7 +22,7 @@ "patterns": [ "_slm/stats" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/slm-api-get-stats.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/slm-api-get-stats.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.get_status.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.get_status.json index 0bc8a51258e54..3aa39e5227cb1 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.get_status.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.get_status.json @@ -4,7 +4,17 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], + "timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "GET" @@ -12,7 +22,7 @@ "patterns": [ "_slm/status" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-get-status.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/slm-api-get-status.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.put_lifecycle.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.put_lifecycle.json index cf700d2b8b198..9105426efb55a 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.put_lifecycle.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.put_lifecycle.json @@ -22,7 +22,7 @@ "patterns": [ "_slm/policy/{policy_id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-put-policy.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/slm-api-put-policy.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.start.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.start.json index 6f1eaab8ba1f4..878b7d1d93706 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.start.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.start.json @@ -4,7 +4,17 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], + "timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "POST" @@ -12,7 +22,7 @@ "patterns": [ "_slm/start" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-start.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/slm-api-start.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.stop.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.stop.json index 6241e9b0751ae..38ad43bdc2ae7 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.stop.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/slm.stop.json @@ -4,7 +4,17 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ], + "timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "POST" @@ -12,7 +22,7 @@ "patterns": [ "_slm/stop" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-stop.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/slm-api-stop.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.cleanup_repository.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.cleanup_repository.json index abab30e3e3e19..072c430b20062 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.cleanup_repository.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.cleanup_repository.json @@ -22,7 +22,7 @@ "patterns": [ "_snapshot/{repository}/_cleanup" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/clean-up-snapshot-repo-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/clean-up-snapshot-repo-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.clone.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.clone.json index ea4183eebe768..1601984497e5c 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.clone.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.clone.json @@ -6,10 +6,12 @@ "human": "__flag__", "pretty": "__flag__", "master_timeout": [ + "30s", "-1", "0" ], "timeout": [ + "30s", "-1", "0" ] @@ -20,7 +22,7 @@ "patterns": [ "_snapshot/{repository}/{snapshot}/_clone/{target_snapshot}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/clone-snapshot-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.create.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.create.json index 38a55a5f6d59c..b116f3ba5ec0a 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.create.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.create.json @@ -19,7 +19,7 @@ "patterns": [ "_snapshot/{repository}/{snapshot}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/create-snapshot-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.create_repository.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.create_repository.json index c3adb5e8e9ed7..6b4083bc5c1c4 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.create_repository.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.create_repository.json @@ -6,10 +6,12 @@ "human": "__flag__", "pretty": "__flag__", "master_timeout": [ + "30s", "-1", "0" ], "timeout": [ + "30s", "-1", "0" ], @@ -22,7 +24,7 @@ "patterns": [ "_snapshot/{repository}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/put-snapshot-repo-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.delete.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.delete.json index ae71d1e53c028..60d5a1a33cce8 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.delete.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.delete.json @@ -6,6 +6,7 @@ "human": "__flag__", "pretty": "__flag__", "master_timeout": [ + "30s", "-1", "0" ] @@ -16,7 +17,7 @@ "patterns": [ "_snapshot/{repository}/{snapshot}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/delete-snapshot-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.delete_repository.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.delete_repository.json index 3b9504afc2d74..4e1d1617a7eca 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.delete_repository.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.delete_repository.json @@ -6,10 +6,12 @@ "human": "__flag__", "pretty": "__flag__", "master_timeout": [ + "30s", "-1", "0" ], "timeout": [ + "30s", "-1", "0" ] @@ -20,7 +22,7 @@ "patterns": [ "_snapshot/{repository}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/delete-snapshot-repo-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.get.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.get.json index eeef215f6b422..bc339a6ad9dbb 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.get.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.get.json @@ -5,16 +5,24 @@ "filter_path": [], "human": "__flag__", "pretty": "__flag__", + "after": "", + "from_sort_value": "", "ignore_unavailable": "__flag__", + "index_details": "__flag__", + "index_names": "__flag__", + "include_repository": "__flag__", "master_timeout": [ "30s", "-1", "0" ], - "verbose": "__flag__", - "index_details": "__flag__", - "index_names": "__flag__", - "include_repository": "__flag__", + "order": [ + "asc", + "desc" + ], + "offset": "", + "size": "", + "slm_policy_filter": "", "sort": [ "start_time", "duration", @@ -24,15 +32,7 @@ "shard_count", "failed_shard_count" ], - "size": "", - "order": [ - "asc", - "desc" - ], - "after": "", - "offset": "", - "from_sort_value": "", - "slm_policy_filter": "" + "verbose": "__flag__" }, "methods": [ "GET" @@ -40,7 +40,7 @@ "patterns": [ "_snapshot/{repository}/{snapshot}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/get-snapshot-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.get_repository.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.get_repository.json index d1d8e3fa2d1c2..86d36776e4fa5 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.get_repository.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.get_repository.json @@ -7,6 +7,7 @@ "pretty": "__flag__", "local": "__flag__", "master_timeout": [ + "to 30s", "-1", "0" ] @@ -18,7 +19,7 @@ "_snapshot", "_snapshot/{repository}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/get-snapshot-repo-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.repository_verify_integrity.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.repository_verify_integrity.json index d23a9bba4b323..0da9b9a8ff8f8 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.repository_verify_integrity.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.repository_verify_integrity.json @@ -5,14 +5,22 @@ "filter_path": [], "human": "__flag__", "pretty": "__flag__", + "blob_thread_pool_concurrency": [ + "1" + ], + "index_snapshot_verification_concurrency": [ + "1" + ], + "index_verification_concurrency": "", + "max_bytes_per_sec": [ + "10mb" + ], + "max_failed_shard_snapshots": [ + "10000" + ], "meta_thread_pool_concurrency": "", - "blob_thread_pool_concurrency": "", "snapshot_verification_concurrency": "", - "index_verification_concurrency": "", - "index_snapshot_verification_concurrency": "", - "max_failed_shard_snapshots": "", - "verify_blob_contents": "__flag__", - "max_bytes_per_sec": "" + "verify_blob_contents": "__flag__" }, "methods": [ "POST" @@ -20,7 +28,7 @@ "patterns": [ "_snapshot/{repository}/_verify_integrity" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/verify-repo-integrity-api.html", "availability": { "stack": false, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.restore.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.restore.json index 67e25e9866649..c624d843afd1c 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.restore.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.restore.json @@ -6,6 +6,7 @@ "human": "__flag__", "pretty": "__flag__", "master_timeout": [ + "30s", "-1", "0" ], @@ -17,7 +18,7 @@ "patterns": [ "_snapshot/{repository}/{snapshot}/_restore" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/restore-snapshot-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.status.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.status.json index 1b63ce16cde66..d061e53943855 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.status.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.status.json @@ -7,6 +7,7 @@ "pretty": "__flag__", "ignore_unavailable": "__flag__", "master_timeout": [ + "30s", "-1", "0" ] @@ -19,7 +20,7 @@ "_snapshot/{repository}/_status", "_snapshot/{repository}/{snapshot}/_status" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/get-snapshot-status-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.verify_repository.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.verify_repository.json index 7b38ce343a446..37c2cee465ae3 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.verify_repository.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/snapshot.verify_repository.json @@ -6,10 +6,12 @@ "human": "__flag__", "pretty": "__flag__", "master_timeout": [ + "30s", "-1", "0" ], "timeout": [ + "30s", "-1", "0" ] @@ -20,7 +22,7 @@ "patterns": [ "_snapshot/{repository}/_verify" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/verify-snapshot-repo-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.clear_cursor.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.clear_cursor.json index f66c1e55c31e4..4152e2e867167 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.clear_cursor.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.clear_cursor.json @@ -12,7 +12,7 @@ "patterns": [ "_sql/close" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/clear-sql-cursor-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/clear-sql-cursor-api.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.delete_async.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.delete_async.json index 184d2f2a16445..f42644185859a 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.delete_async.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.delete_async.json @@ -12,7 +12,7 @@ "patterns": [ "_sql/async/delete/{id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/delete-async-sql-search-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/delete-async-sql-search-api.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.get_async.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.get_async.json index 4a24f3f2b1563..87e84ad78609d 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.get_async.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.get_async.json @@ -24,7 +24,7 @@ "patterns": [ "_sql/async/{id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/get-async-sql-search-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/get-async-sql-search-api.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.get_async_status.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.get_async_status.json index 7d4a714a1e77d..157b8bbe1a4e7 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.get_async_status.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.get_async_status.json @@ -12,7 +12,7 @@ "patterns": [ "_sql/async/status/{id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/get-async-sql-search-status-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/get-async-sql-search-status-api.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.query.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.query.json index 48ea948fd22ae..473130825cfd6 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.query.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.query.json @@ -22,7 +22,7 @@ "patterns": [ "_sql" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-search-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/sql-search-api.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.translate.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.translate.json index fda9def4a1b5b..788951b069505 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.translate.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/sql.translate.json @@ -13,7 +13,7 @@ "patterns": [ "_sql/translate" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-translate-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/sql-translate-api.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.delete_synonym.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.delete_synonym.json index 9c2b72d8d3a6c..5859502dc1bb3 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.delete_synonym.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.delete_synonym.json @@ -12,7 +12,7 @@ "patterns": [ "_synonyms/{id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/delete-synonyms-set.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/delete-synonyms-set.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.delete_synonym_rule.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.delete_synonym_rule.json index fc5b150337d89..5fb58764cd3d8 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.delete_synonym_rule.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.delete_synonym_rule.json @@ -12,7 +12,7 @@ "patterns": [ "_synonyms/{set_id}/{rule_id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/delete-synonym-rule.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/delete-synonym-rule.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.get_synonym.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.get_synonym.json index b180ea625639a..810c945348ca5 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.get_synonym.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.get_synonym.json @@ -16,7 +16,7 @@ "patterns": [ "_synonyms/{id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/get-synonyms-set.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/get-synonyms-set.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.get_synonym_rule.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.get_synonym_rule.json index b6c0a7c2e523c..2f0ecc17987d4 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.get_synonym_rule.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.get_synonym_rule.json @@ -12,7 +12,7 @@ "patterns": [ "_synonyms/{set_id}/{rule_id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/get-synonym-rule.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/get-synonym-rule.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.get_synonyms_sets.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.get_synonyms_sets.json index 894bf417ef41b..7198e076d3f84 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.get_synonyms_sets.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.get_synonyms_sets.json @@ -16,7 +16,7 @@ "patterns": [ "_synonyms" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/list-synonyms-sets.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/get-synonyms-set.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.put_synonym.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.put_synonym.json index 519e2df3a7d69..574a1cdf490dd 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.put_synonym.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.put_synonym.json @@ -12,7 +12,7 @@ "patterns": [ "_synonyms/{id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/put-synonyms-set.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/put-synonyms-set.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.put_synonym_rule.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.put_synonym_rule.json index 96dec0f4b5d40..768f366f8b240 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.put_synonym_rule.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/synonyms.put_synonym_rule.json @@ -12,7 +12,7 @@ "patterns": [ "_synonyms/{set_id}/{rule_id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/put-synonym-rule.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/put-synonym-rule.html", "availability": { "stack": true, "serverless": true diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/tasks.list.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/tasks.list.json index 3e934056209c7..7f64923715b41 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/tasks.list.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/tasks.list.json @@ -14,11 +14,6 @@ ], "nodes": [], "parent_task_id": "", - "master_timeout": [ - "30s", - "-1", - "0" - ], "timeout": [ "30s", "-1", diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/text_structure.find_field_structure.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/text_structure.find_field_structure.json index 08d0ca5f33c4f..13340f508af4e 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/text_structure.find_field_structure.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/text_structure.find_field_structure.json @@ -1,12 +1,46 @@ { "text_structure.find_field_structure": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__", + "column_names": "", + "delimiter": "", + "documents_to_sample": [ + "1000" + ], + "ecs_compatibility": [ + "disabled", + "v1" + ], + "explain": "__flag__", + "field": "", + "format": [ + "delimited", + "ndjson", + "semi_structured_text", + "xml" + ], + "grok_pattern": "", + "index": "", + "quote": "", + "should_trim_fields": "__flag__", + "timeout": [ + "25s", + "-1", + "0" + ], + "timestamp_field": "", + "timestamp_format": "" + }, "methods": [ "GET" ], "patterns": [ "_text_structure/find_field_structure" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/find-field-structure.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/find-field-structure.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/text_structure.find_message_structure.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/text_structure.find_message_structure.json index 6d01c9d1fc96f..3615817608d90 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/text_structure.find_message_structure.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/text_structure.find_message_structure.json @@ -1,5 +1,34 @@ { "text_structure.find_message_structure": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__", + "column_names": "", + "delimiter": "", + "ecs_compatibility": [ + "disabled", + "v1" + ], + "explain": "__flag__", + "format": [ + "delimited", + "ndjson", + "semi_structured_text", + "xml" + ], + "grok_pattern": "", + "quote": "", + "should_trim_fields": "__flag__", + "timeout": [ + "25s", + "-1", + "0" + ], + "timestamp_field": "", + "timestamp_format": "" + }, "methods": [ "GET", "POST" @@ -7,7 +36,7 @@ "patterns": [ "_text_structure/find_message_structure" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/find-message-structure.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/find-message-structure.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/text_structure.find_structure.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/text_structure.find_structure.json index 7b0248d640819..6c5c62085a637 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/text_structure.find_structure.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/text_structure.find_structure.json @@ -4,7 +4,9 @@ "charset": "", "column_names": "", "delimiter": "", - "ecs_compatibility": "", + "ecs_compatibility": [ + "disabled" + ], "explain": "__flag__", "format": "", "grok_pattern": "", @@ -31,7 +33,7 @@ "patterns": [ "_text_structure/find_structure" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/find-structure.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/find-structure.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/text_structure.test_grok_pattern.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/text_structure.test_grok_pattern.json index a22f3d9891646..7d2754c7784da 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/text_structure.test_grok_pattern.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/text_structure.test_grok_pattern.json @@ -5,7 +5,9 @@ "filter_path": [], "human": "__flag__", "pretty": "__flag__", - "ecs_compatibility": "" + "ecs_compatibility": [ + "disabled" + ] }, "methods": [ "GET", diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/transform.reset_transform.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/transform.reset_transform.json index dfc0e1a446c98..bd9ea79afe927 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/transform.reset_transform.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/transform.reset_transform.json @@ -5,7 +5,12 @@ "filter_path": [], "human": "__flag__", "pretty": "__flag__", - "force": "__flag__" + "force": "__flag__", + "timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "POST" diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.ack_watch.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.ack_watch.json index b021e63d20dc1..20080f17a6688 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.ack_watch.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.ack_watch.json @@ -14,7 +14,7 @@ "_watcher/watch/{watch_id}/_ack", "_watcher/watch/{watch_id}/_ack/{action_id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-ack-watch.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/watcher-api-ack-watch.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.activate_watch.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.activate_watch.json index 7e02bf603581c..ae351ec2b593a 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.activate_watch.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.activate_watch.json @@ -13,7 +13,7 @@ "patterns": [ "_watcher/watch/{watch_id}/_activate" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-activate-watch.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/watcher-api-activate-watch.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.deactivate_watch.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.deactivate_watch.json index 7528c0aefb75c..92ea41463bbf1 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.deactivate_watch.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.deactivate_watch.json @@ -13,7 +13,7 @@ "patterns": [ "_watcher/watch/{watch_id}/_deactivate" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-deactivate-watch.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/watcher-api-deactivate-watch.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.delete_watch.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.delete_watch.json index ca086d1ae47a8..6e67e91ea451d 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.delete_watch.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.delete_watch.json @@ -12,7 +12,7 @@ "patterns": [ "_watcher/watch/{id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-delete-watch.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/watcher-api-delete-watch.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.execute_watch.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.execute_watch.json index 5059d98b578f1..a723f9c32d37f 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.execute_watch.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.execute_watch.json @@ -15,7 +15,7 @@ "_watcher/watch/{id}/_execute", "_watcher/watch/_execute" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-execute-watch.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/watcher-api-execute-watch.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.get_settings.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.get_settings.json index 5149f0ba020a3..b0cf872b02ab8 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.get_settings.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.get_settings.json @@ -1,12 +1,22 @@ { "watcher.get_settings": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__", + "master_timeout": [ + "-1", + "0" + ] + }, "methods": [ "GET" ], "patterns": [ "_watcher/settings" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-get-settings.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/watcher-api-get-settings.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.get_watch.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.get_watch.json index a7f197170c8e4..c80ae022ac9af 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.get_watch.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.get_watch.json @@ -12,7 +12,7 @@ "patterns": [ "_watcher/watch/{id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-get-watch.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/watcher-api-get-watch.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.put_watch.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.put_watch.json index 4ca82e48e2427..a8be4de2255a5 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.put_watch.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.put_watch.json @@ -17,7 +17,7 @@ "patterns": [ "_watcher/watch/{id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-put-watch.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/watcher-api-put-watch.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.query_watches.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.query_watches.json index 64c65a755c13b..4302406d93a1e 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.query_watches.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.query_watches.json @@ -13,7 +13,7 @@ "patterns": [ "_watcher/_query/watches" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-query-watches.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/watcher-api-query-watches.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.start.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.start.json index 85b9b6b7ffb36..7bce97ed1e192 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.start.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.start.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "POST" @@ -12,7 +17,7 @@ "patterns": [ "_watcher/_start" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-start.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/watcher-api-start.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.stats.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.stats.json index 35d5e21669a39..4d5adb6c72d6c 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.stats.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.stats.json @@ -28,7 +28,7 @@ "_watcher/stats", "_watcher/stats/{metric}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-stats.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/watcher-api-stats.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.stop.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.stop.json index 1ea4956c1b114..7455b406af590 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.stop.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.stop.json @@ -4,7 +4,12 @@ "error_trace": "__flag__", "filter_path": [], "human": "__flag__", - "pretty": "__flag__" + "pretty": "__flag__", + "master_timeout": [ + "30s", + "-1", + "0" + ] }, "methods": [ "POST" @@ -12,7 +17,7 @@ "patterns": [ "_watcher/_stop" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-stop.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/watcher-api-stop.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.update_settings.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.update_settings.json index fdc03672ee1a7..8dfd8c9674a48 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.update_settings.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/watcher.update_settings.json @@ -1,12 +1,26 @@ { "watcher.update_settings": { + "url_params": { + "error_trace": "__flag__", + "filter_path": [], + "human": "__flag__", + "pretty": "__flag__", + "master_timeout": [ + "-1", + "0" + ], + "timeout": [ + "-1", + "0" + ] + }, "methods": [ "PUT" ], "patterns": [ "_watcher/settings" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-update-settings.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/watcher-api-update-settings.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/xpack.info.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/xpack.info.json index 4181deb315ff7..8525afbdf49da 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/xpack.info.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/xpack.info.json @@ -18,7 +18,7 @@ "patterns": [ "_xpack" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/info-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/info-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/xpack.usage.json b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/xpack.usage.json index 626f8271e6501..342680eb06544 100644 --- a/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/xpack.usage.json +++ b/src/platform/plugins/shared/console/server/lib/spec_definitions/json/generated/xpack.usage.json @@ -17,7 +17,7 @@ "patterns": [ "_xpack/usage" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/usage-api.html", + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/{branch}/usage-api.html", "availability": { "stack": true, "serverless": false diff --git a/src/platform/plugins/shared/controls/public/actions/clear_control_action.tsx b/src/platform/plugins/shared/controls/public/actions/clear_control_action.tsx index 06f9b26c04ddc..f435f7e885c5b 100644 --- a/src/platform/plugins/shared/controls/public/actions/clear_control_action.tsx +++ b/src/platform/plugins/shared/controls/public/actions/clear_control_action.tsx @@ -11,15 +11,43 @@ import React, { SyntheticEvent } from 'react'; import { EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import type { EmbeddableApiContext, HasUniqueId } from '@kbn/presentation-publishing'; +import { + apiCanAccessViewMode, + apiHasParentApi, + apiHasType, + apiHasUniqueId, + apiIsOfType, + HasParentApi, + type EmbeddableApiContext, + type HasUniqueId, + HasType, +} from '@kbn/presentation-publishing'; import { IncompatibleActionError, FrequentCompatibilityChangeAction, type Action, } from '@kbn/ui-actions-plugin/public'; -import { isClearableControl } from '../types'; +import { PresentationContainer, apiIsPresentationContainer } from '@kbn/presentation-containers'; +import { CONTROL_GROUP_TYPE } from '../../common'; +import { CanClearSelections, isClearableControl } from '../types'; + +import { ACTION_CLEAR_CONTROL } from './constants'; + +type ClearControlActionApi = HasType & + HasUniqueId & + CanClearSelections & + HasParentApi; -import { ACTION_CLEAR_CONTROL } from '.'; +const compatibilityCheck = (api: unknown | null): api is ClearControlActionApi => + Boolean( + apiHasType(api) && + apiHasUniqueId(api) && + isClearableControl(api) && + apiHasParentApi(api) && + apiCanAccessViewMode(api.parentApi) && + apiIsOfType(api.parentApi, CONTROL_GROUP_TYPE) && + apiIsPresentationContainer(api.parentApi) + ); export class ClearControlAction implements Action, FrequentCompatibilityChangeAction @@ -73,12 +101,10 @@ export class ClearControlAction } public async isCompatible({ embeddable }: EmbeddableApiContext) { - const { isCompatible } = await import('./clear_control_action_compatibility_check'); - return isCompatible(embeddable); + return compatibilityCheck(embeddable); } public async execute({ embeddable }: EmbeddableApiContext) { - const { compatibilityCheck } = await import('./clear_control_action_compatibility_check'); if (!compatibilityCheck(embeddable)) throw new IncompatibleActionError(); embeddable.clearSelections(); diff --git a/src/platform/plugins/shared/controls/public/actions/clear_control_action_compatibility_check.ts b/src/platform/plugins/shared/controls/public/actions/clear_control_action_compatibility_check.ts deleted file mode 100644 index f04cb91bc9a3a..0000000000000 --- a/src/platform/plugins/shared/controls/public/actions/clear_control_action_compatibility_check.ts +++ /dev/null @@ -1,42 +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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { PresentationContainer, apiIsPresentationContainer } from '@kbn/presentation-containers'; -import { - HasParentApi, - HasType, - HasUniqueId, - apiCanAccessViewMode, - apiHasParentApi, - apiHasType, - apiHasUniqueId, - apiIsOfType, -} from '@kbn/presentation-publishing'; -import { CONTROL_GROUP_TYPE } from '../../common'; -import { isClearableControl, type CanClearSelections } from '../types'; - -type ClearControlActionApi = HasType & - HasUniqueId & - CanClearSelections & - HasParentApi; - -export const compatibilityCheck = (api: unknown | null): api is ClearControlActionApi => - Boolean( - apiHasType(api) && - apiHasUniqueId(api) && - isClearableControl(api) && - apiHasParentApi(api) && - apiCanAccessViewMode(api.parentApi) && - apiIsOfType(api.parentApi, CONTROL_GROUP_TYPE) && - apiIsPresentationContainer(api.parentApi) - ); - -export function isCompatible(api: unknown) { - return compatibilityCheck(api); -} diff --git a/src/platform/plugins/shared/controls/public/actions/index.ts b/src/platform/plugins/shared/controls/public/actions/constants.ts similarity index 100% rename from src/platform/plugins/shared/controls/public/actions/index.ts rename to src/platform/plugins/shared/controls/public/actions/constants.ts diff --git a/src/platform/plugins/shared/controls/public/actions/controls_hover_trigger.ts b/src/platform/plugins/shared/controls/public/actions/controls_hover_trigger.ts new file mode 100644 index 0000000000000..d4f62495a656c --- /dev/null +++ b/src/platform/plugins/shared/controls/public/actions/controls_hover_trigger.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { Trigger } from '@kbn/ui-actions-plugin/public'; + +export const CONTROL_HOVER_TRIGGER = 'CONTROL_HOVER_TRIGGER'; +export const controlHoverTrigger: Trigger = { + id: CONTROL_HOVER_TRIGGER, + title: i18n.translate('controls.hoverTrigger.title', { + defaultMessage: 'Control hover', + }), + description: i18n.translate('controls.hoverTrigger.description', { + defaultMessage: "Add action to controls's hover menu", + }), +}; diff --git a/src/platform/plugins/shared/controls/public/actions/delete_control_action.tsx b/src/platform/plugins/shared/controls/public/actions/delete_control_action.tsx index 7ee55ddd3da69..5ef40e7443b63 100644 --- a/src/platform/plugins/shared/controls/public/actions/delete_control_action.tsx +++ b/src/platform/plugins/shared/controls/public/actions/delete_control_action.tsx @@ -11,12 +11,40 @@ import React from 'react'; import { EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import type { HasUniqueId, EmbeddableApiContext } from '@kbn/presentation-publishing'; +import { + type HasUniqueId, + type EmbeddableApiContext, + type HasType, + type HasParentApi, + type PublishesViewMode, + apiHasType, + apiHasUniqueId, + apiHasParentApi, + apiCanAccessViewMode, + apiIsOfType, + getInheritedViewMode, +} from '@kbn/presentation-publishing'; import { IncompatibleActionError, type Action } from '@kbn/ui-actions-plugin/public'; -import { ACTION_DELETE_CONTROL } from '.'; +import { PresentationContainer, apiIsPresentationContainer } from '@kbn/presentation-containers'; +import { CONTROL_GROUP_TYPE } from '../../common'; +import { ACTION_DELETE_CONTROL } from './constants'; import { coreServices } from '../services/kibana_services'; +type DeleteControlActionApi = HasType & + HasUniqueId & + HasParentApi; + +export const compatibilityCheck = (api: unknown | null): api is DeleteControlActionApi => + Boolean( + apiHasType(api) && + apiHasUniqueId(api) && + apiHasParentApi(api) && + apiCanAccessViewMode(api.parentApi) && + apiIsOfType(api.parentApi, CONTROL_GROUP_TYPE) && + apiIsPresentationContainer(api.parentApi) + ); + export class DeleteControlAction implements Action { public readonly type = ACTION_DELETE_CONTROL; public readonly id = ACTION_DELETE_CONTROL; @@ -49,12 +77,10 @@ export class DeleteControlAction implements Action { } public async isCompatible({ embeddable }: EmbeddableApiContext) { - const { isCompatible } = await import('./delete_control_action_compatibility_check'); - return isCompatible(embeddable); + return compatibilityCheck(embeddable) && getInheritedViewMode(embeddable.parentApi) === 'edit'; } public async execute({ embeddable }: EmbeddableApiContext) { - const { compatibilityCheck } = await import('./delete_control_action_compatibility_check'); if (!compatibilityCheck(embeddable)) throw new IncompatibleActionError(); coreServices.overlays diff --git a/src/platform/plugins/shared/controls/public/actions/delete_control_action_compatibility_check.ts b/src/platform/plugins/shared/controls/public/actions/delete_control_action_compatibility_check.ts deleted file mode 100644 index a09b3448b2fc1..0000000000000 --- a/src/platform/plugins/shared/controls/public/actions/delete_control_action_compatibility_check.ts +++ /dev/null @@ -1,42 +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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ViewMode } from '@kbn/embeddable-plugin/public'; -import { PresentationContainer, apiIsPresentationContainer } from '@kbn/presentation-containers'; -import { - HasParentApi, - HasType, - HasUniqueId, - PublishesViewMode, - apiCanAccessViewMode, - apiHasParentApi, - apiHasType, - apiHasUniqueId, - apiIsOfType, - getInheritedViewMode, -} from '@kbn/presentation-publishing'; -import { CONTROL_GROUP_TYPE } from '../../common'; - -type DeleteControlActionApi = HasType & - HasUniqueId & - HasParentApi; - -export const compatibilityCheck = (api: unknown | null): api is DeleteControlActionApi => - Boolean( - apiHasType(api) && - apiHasUniqueId(api) && - apiHasParentApi(api) && - apiCanAccessViewMode(api.parentApi) && - apiIsOfType(api.parentApi, CONTROL_GROUP_TYPE) && - apiIsPresentationContainer(api.parentApi) - ); - -export function isCompatible(api: unknown) { - return compatibilityCheck(api) && getInheritedViewMode(api.parentApi) === ViewMode.EDIT; -} diff --git a/src/platform/plugins/shared/controls/public/actions/edit_control_action.tsx b/src/platform/plugins/shared/controls/public/actions/edit_control_action.tsx index 0dec1a610d9d4..e8244f4229545 100644 --- a/src/platform/plugins/shared/controls/public/actions/edit_control_action.tsx +++ b/src/platform/plugins/shared/controls/public/actions/edit_control_action.tsx @@ -11,10 +11,35 @@ import React from 'react'; import { EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import type { EmbeddableApiContext, HasUniqueId } from '@kbn/presentation-publishing'; +import { + apiHasType, + apiHasUniqueId, + hasEditCapabilities, + type EmbeddableApiContext, + type HasUniqueId, + apiHasParentApi, + apiCanAccessViewMode, + apiIsOfType, + getInheritedViewMode, +} from '@kbn/presentation-publishing'; import { IncompatibleActionError, type Action } from '@kbn/ui-actions-plugin/public'; -import { ACTION_EDIT_CONTROL } from '.'; +import { apiIsPresentationContainer } from '@kbn/presentation-containers'; +import { CONTROL_GROUP_TYPE } from '../../common'; +import { ACTION_EDIT_CONTROL } from './constants'; +import { DataControlApi } from '../controls/data_controls/types'; + +const compatibilityCheck = (api: unknown): api is DataControlApi => { + return Boolean( + apiHasType(api) && + apiHasUniqueId(api) && + hasEditCapabilities(api) && + apiHasParentApi(api) && + apiCanAccessViewMode(api.parentApi) && + apiIsOfType(api.parentApi, CONTROL_GROUP_TYPE) && + apiIsPresentationContainer(api.parentApi) + ); +}; export class EditControlAction implements Action { public readonly type = ACTION_EDIT_CONTROL; @@ -48,12 +73,14 @@ export class EditControlAction implements Action { } public async isCompatible({ embeddable }: EmbeddableApiContext) { - const { isCompatible } = await import('./edit_control_action_compatibility_check'); - return isCompatible(embeddable); + return ( + compatibilityCheck(embeddable) && + getInheritedViewMode(embeddable.parentApi) === 'edit' && + embeddable.isEditingEnabled() + ); } public async execute({ embeddable }: EmbeddableApiContext) { - const { compatibilityCheck } = await import('./edit_control_action_compatibility_check'); if (!compatibilityCheck(embeddable)) throw new IncompatibleActionError(); await embeddable.onEdit(); } diff --git a/src/platform/plugins/shared/controls/public/actions/edit_control_action_compatibility_check.ts b/src/platform/plugins/shared/controls/public/actions/edit_control_action_compatibility_check.ts deleted file mode 100644 index 0af5a942dd032..0000000000000 --- a/src/platform/plugins/shared/controls/public/actions/edit_control_action_compatibility_check.ts +++ /dev/null @@ -1,43 +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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ViewMode } from '@kbn/embeddable-plugin/public'; -import { apiIsPresentationContainer } from '@kbn/presentation-containers'; -import { - apiCanAccessViewMode, - apiHasParentApi, - apiHasType, - apiHasUniqueId, - apiIsOfType, - getInheritedViewMode, - hasEditCapabilities, -} from '@kbn/presentation-publishing'; - -import { CONTROL_GROUP_TYPE } from '../../common'; -import { DataControlApi } from '../controls/data_controls/types'; - -export const compatibilityCheck = (api: unknown): api is DataControlApi => { - return Boolean( - apiHasType(api) && - apiHasUniqueId(api) && - hasEditCapabilities(api) && - apiHasParentApi(api) && - apiCanAccessViewMode(api.parentApi) && - apiIsOfType(api.parentApi, CONTROL_GROUP_TYPE) && - apiIsPresentationContainer(api.parentApi) - ); -}; - -export function isCompatible(api: unknown) { - return ( - compatibilityCheck(api) && - getInheritedViewMode(api.parentApi) === ViewMode.EDIT && - api.isEditingEnabled() - ); -} diff --git a/src/platform/plugins/shared/controls/public/actions/register_actions.ts b/src/platform/plugins/shared/controls/public/actions/register_actions.ts new file mode 100644 index 0000000000000..0d6097759ea6a --- /dev/null +++ b/src/platform/plugins/shared/controls/public/actions/register_actions.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { UiActionsStart } from '@kbn/ui-actions-plugin/public'; +import { ACTION_CLEAR_CONTROL, ACTION_DELETE_CONTROL, ACTION_EDIT_CONTROL } from './constants'; +import { CONTROL_HOVER_TRIGGER, controlHoverTrigger } from './controls_hover_trigger'; + +export function registerActions(uiActions: UiActionsStart) { + uiActions.registerTrigger(controlHoverTrigger); + + uiActions.registerActionAsync(ACTION_DELETE_CONTROL, async () => { + const { DeleteControlAction } = await import('../controls_module'); + return new DeleteControlAction(); + }); + uiActions.attachAction(CONTROL_HOVER_TRIGGER, ACTION_DELETE_CONTROL); + + uiActions.registerActionAsync(ACTION_EDIT_CONTROL, async () => { + const { EditControlAction } = await import('../controls_module'); + return new EditControlAction(); + }); + uiActions.attachAction(CONTROL_HOVER_TRIGGER, ACTION_EDIT_CONTROL); + + uiActions.registerActionAsync(ACTION_CLEAR_CONTROL, async () => { + const { ClearControlAction } = await import('../controls_module'); + return new ClearControlAction(); + }); + uiActions.attachAction(CONTROL_HOVER_TRIGGER, ACTION_CLEAR_CONTROL); +} diff --git a/src/platform/plugins/shared/controls/public/control_group/components/control_panel.test.tsx b/src/platform/plugins/shared/controls/public/control_group/components/control_panel.test.tsx index 0f6d8b07b324a..ad2a1461a1d5b 100644 --- a/src/platform/plugins/shared/controls/public/control_group/components/control_panel.test.tsx +++ b/src/platform/plugins/shared/controls/public/control_group/components/control_panel.test.tsx @@ -11,12 +11,12 @@ import React, { useImperativeHandle } from 'react'; import { BehaviorSubject } from 'rxjs'; import { setMockedPresentationUtilServices } from '@kbn/presentation-util-plugin/public/mocks'; -import { uiActionsService } from '@kbn/presentation-util-plugin/public/services/kibana_services'; import { render, waitFor } from '@testing-library/react'; +import { Action } from '@kbn/ui-actions-plugin/public'; import type { ControlLabelPosition, ControlWidth } from '../../../common'; +import { uiActionsService } from '../../services/kibana_services'; import { ControlPanel } from './control_panel'; -import { Action } from '@kbn/ui-actions-plugin/public'; describe('render', () => { let mockApi = {}; diff --git a/src/platform/plugins/shared/controls/public/control_group/components/control_panel.tsx b/src/platform/plugins/shared/controls/public/control_group/components/control_panel.tsx index acff284eeba1f..9a21c28eb2f1d 100644 --- a/src/platform/plugins/shared/controls/public/control_group/components/control_panel.tsx +++ b/src/platform/plugins/shared/controls/public/control_group/components/control_panel.tsx @@ -27,7 +27,7 @@ import { apiPublishesViewMode, useBatchedOptionalPublishingSubjects, } from '@kbn/presentation-publishing'; -import { FloatingActions } from '@kbn/presentation-util-plugin/public'; +import { FloatingActions } from './floating_actions'; import { DEFAULT_CONTROL_GROW, DEFAULT_CONTROL_WIDTH } from '../../../common'; import { ControlPanelProps, DefaultControlApi } from '../../controls/types'; diff --git a/src/platform/plugins/shared/presentation_util/public/components/floating_actions/floating_actions.scss b/src/platform/plugins/shared/controls/public/control_group/components/floating_actions.scss similarity index 100% rename from src/platform/plugins/shared/presentation_util/public/components/floating_actions/floating_actions.scss rename to src/platform/plugins/shared/controls/public/control_group/components/floating_actions.scss diff --git a/src/platform/plugins/shared/presentation_util/public/components/floating_actions/floating_actions.tsx b/src/platform/plugins/shared/controls/public/control_group/components/floating_actions.tsx similarity index 91% rename from src/platform/plugins/shared/presentation_util/public/components/floating_actions/floating_actions.tsx rename to src/platform/plugins/shared/controls/public/control_group/components/floating_actions.tsx index 33d03058810c9..b6c51619eda0e 100644 --- a/src/platform/plugins/shared/presentation_util/public/components/floating_actions/floating_actions.tsx +++ b/src/platform/plugins/shared/controls/public/control_group/components/floating_actions.tsx @@ -12,16 +12,13 @@ import React, { FC, ReactElement, useEffect, useState } from 'react'; import { v4 } from 'uuid'; import { Subscription } from 'rxjs'; -import { - PANEL_HOVER_TRIGGER, - panelHoverTrigger, - type ViewMode, -} from '@kbn/embeddable-plugin/public'; +import { type ViewMode } from '@kbn/embeddable-plugin/public'; import { apiHasUniqueId } from '@kbn/presentation-publishing'; import { Action } from '@kbn/ui-actions-plugin/public'; import { AnyApiAction } from '@kbn/presentation-panel-plugin/public/panel_actions/types'; import { uiActionsService } from '../../services/kibana_services'; import './floating_actions.scss'; +import { CONTROL_HOVER_TRIGGER, controlHoverTrigger } from '../../actions/controls_hover_trigger'; export interface FloatingActionsProps { children: ReactElement; @@ -53,7 +50,7 @@ export const FloatingActions: FC = ({ let canceled = false; const context = { embeddable: api, - trigger: panelHoverTrigger, + trigger: controlHoverTrigger, }; const sortByOrder = (a: Action | FloatingActionItem, b: Action | FloatingActionItem) => { @@ -62,7 +59,7 @@ export const FloatingActions: FC = ({ const getActions: () => Promise = async () => { const actions = ( - await uiActionsService.getTriggerCompatibleActions(PANEL_HOVER_TRIGGER, context) + await uiActionsService.getTriggerCompatibleActions(CONTROL_HOVER_TRIGGER, context) ) .filter((action) => { return action.MenuItem !== undefined && (disabledActions ?? []).indexOf(action.id) === -1; @@ -92,7 +89,10 @@ export const FloatingActions: FC = ({ setFloatingActions(actions); const frequentlyChangingActions = - await uiActionsService.getFrequentlyChangingActionsForTrigger(PANEL_HOVER_TRIGGER, context); + await uiActionsService.getFrequentlyChangingActionsForTrigger( + CONTROL_HOVER_TRIGGER, + context + ); if (canceled) return; for (const action of frequentlyChangingActions) { diff --git a/src/platform/plugins/shared/controls/public/control_group/control_group_renderer/control_group_renderer_lazy.tsx b/src/platform/plugins/shared/controls/public/control_group/control_group_renderer/control_group_renderer_lazy.tsx index e4bf8594ceb38..7ef526f6acd7c 100644 --- a/src/platform/plugins/shared/controls/public/control_group/control_group_renderer/control_group_renderer_lazy.tsx +++ b/src/platform/plugins/shared/controls/public/control_group/control_group_renderer/control_group_renderer_lazy.tsx @@ -12,7 +12,7 @@ import { dynamic } from '@kbn/shared-ux-utility'; import type { ControlGroupRendererProps } from './control_group_renderer'; const Component = dynamic(async () => { - const { ControlGroupRenderer } = await import('./control_group_renderer'); + const { ControlGroupRenderer } = await import('../../controls_module'); return { default: ControlGroupRenderer, }; diff --git a/src/platform/plugins/shared/controls/public/control_group/init_controls_manager.ts b/src/platform/plugins/shared/controls/public/control_group/init_controls_manager.ts index 935845327131e..483ac9b9d834b 100644 --- a/src/platform/plugins/shared/controls/public/control_group/init_controls_manager.ts +++ b/src/platform/plugins/shared/controls/public/control_group/init_controls_manager.ts @@ -17,8 +17,11 @@ import type { PanelPackage, PresentationContainer, } from '@kbn/presentation-containers'; -import { apiHasSnapshottableState } from '@kbn/presentation-containers/interfaces/serialized_state'; -import type { PublishingSubject, StateComparators } from '@kbn/presentation-publishing'; +import { + type PublishingSubject, + type StateComparators, + apiHasSnapshottableState, +} from '@kbn/presentation-publishing'; import { BehaviorSubject, first, merge } from 'rxjs'; import type { ControlPanelState, @@ -99,7 +102,7 @@ export function initControlsManager( } async function addNewPanel( - { panelType, initialState }: PanelPackage, + { panelType, initialState }: PanelPackage<{}, DefaultControlState>, index: number ) { if ((initialState as DefaultDataControlState)?.dataViewId) { diff --git a/src/platform/plugins/shared/controls/public/control_group/register_control_group_embeddable.ts b/src/platform/plugins/shared/controls/public/control_group/register_control_group_embeddable.ts index f93458ab6bc4a..8708efda5d830 100644 --- a/src/platform/plugins/shared/controls/public/control_group/register_control_group_embeddable.ts +++ b/src/platform/plugins/shared/controls/public/control_group/register_control_group_embeddable.ts @@ -14,7 +14,7 @@ import { untilPluginStartServicesReady } from '../services/kibana_services'; export function registerControlGroupEmbeddable(embeddableSetup: EmbeddableSetup) { embeddableSetup.registerReactEmbeddableFactory(CONTROL_GROUP_TYPE, async () => { const [{ getControlGroupEmbeddableFactory }] = await Promise.all([ - import('./get_control_group_factory'), + import('../controls_module'), untilPluginStartServicesReady(), ]); return getControlGroupEmbeddableFactory(); diff --git a/src/platform/plugins/shared/controls/public/control_group/utils/serialization_utils.ts b/src/platform/plugins/shared/controls/public/control_group/utils/serialization_utils.ts index 0a046244b732f..b905a8d516ba6 100644 --- a/src/platform/plugins/shared/controls/public/control_group/utils/serialization_utils.ts +++ b/src/platform/plugins/shared/controls/public/control_group/utils/serialization_utils.ts @@ -9,7 +9,7 @@ import { omit } from 'lodash'; -import { SerializedPanelState } from '@kbn/presentation-containers'; +import { SerializedPanelState } from '@kbn/presentation-publishing'; import type { ControlGroupRuntimeState, ControlGroupSerializedState } from '../../../common'; import { parseReferenceName } from '../../controls/data_controls/reference_name_utils'; diff --git a/src/platform/plugins/shared/controls/public/controls/data_controls/initialize_data_control.ts b/src/platform/plugins/shared/controls/public/controls/data_controls/initialize_data_control.ts index 71cb6cfb78245..68affc22ad4cb 100644 --- a/src/platform/plugins/shared/controls/public/controls/data_controls/initialize_data_control.ts +++ b/src/platform/plugins/shared/controls/public/controls/data_controls/initialize_data_control.ts @@ -16,8 +16,7 @@ import { DataViewField, } from '@kbn/data-views-plugin/common'; import { Filter } from '@kbn/es-query'; -import { SerializedPanelState } from '@kbn/presentation-containers'; -import { StateComparators } from '@kbn/presentation-publishing'; +import { StateComparators, SerializedPanelState } from '@kbn/presentation-publishing'; import { i18n } from '@kbn/i18n'; import type { DefaultControlState, DefaultDataControlState } from '../../../common'; diff --git a/src/platform/plugins/shared/controls/public/controls/data_controls/options_list_control/register_options_list_control.ts b/src/platform/plugins/shared/controls/public/controls/data_controls/options_list_control/register_options_list_control.ts index 45f430598fa50..b21864ec90546 100644 --- a/src/platform/plugins/shared/controls/public/controls/data_controls/options_list_control/register_options_list_control.ts +++ b/src/platform/plugins/shared/controls/public/controls/data_controls/options_list_control/register_options_list_control.ts @@ -14,7 +14,7 @@ import { registerControlFactory } from '../../../control_factory_registry'; export function registerOptionsListControl() { registerControlFactory(OPTIONS_LIST_CONTROL, async () => { const [{ getOptionsListControlFactory }] = await Promise.all([ - import('./get_options_list_control_factory'), + import('../../../controls_module'), untilPluginStartServicesReady(), ]); return getOptionsListControlFactory(); diff --git a/src/platform/plugins/shared/controls/public/controls/data_controls/range_slider/get_range_slider_control_factory.test.tsx b/src/platform/plugins/shared/controls/public/controls/data_controls/range_slider/get_range_slider_control_factory.test.tsx index 03ebe50969d05..785ff41a7e48d 100644 --- a/src/platform/plugins/shared/controls/public/controls/data_controls/range_slider/get_range_slider_control_factory.test.tsx +++ b/src/platform/plugins/shared/controls/public/controls/data_controls/range_slider/get_range_slider_control_factory.test.tsx @@ -12,7 +12,7 @@ import { of } from 'rxjs'; import { estypes } from '@elastic/elasticsearch'; import { DataViewField } from '@kbn/data-views-plugin/common'; -import { SerializedPanelState } from '@kbn/presentation-containers'; +import { SerializedPanelState } from '@kbn/presentation-publishing'; import { fireEvent, render, waitFor } from '@testing-library/react'; import { dataService, dataViewsService } from '../../../services/kibana_services'; diff --git a/src/platform/plugins/shared/controls/public/controls/data_controls/range_slider/register_range_slider_control.ts b/src/platform/plugins/shared/controls/public/controls/data_controls/range_slider/register_range_slider_control.ts index 9f7af0ccae2c3..a2ee5f4822de8 100644 --- a/src/platform/plugins/shared/controls/public/controls/data_controls/range_slider/register_range_slider_control.ts +++ b/src/platform/plugins/shared/controls/public/controls/data_controls/range_slider/register_range_slider_control.ts @@ -14,7 +14,7 @@ import { registerControlFactory } from '../../../control_factory_registry'; export function registerRangeSliderControl() { registerControlFactory(RANGE_SLIDER_CONTROL, async () => { const [{ getRangesliderControlFactory }] = await Promise.all([ - import('./get_range_slider_control_factory'), + import('../../../controls_module'), untilPluginStartServicesReady(), ]); diff --git a/src/platform/plugins/shared/controls/public/controls/initialize_default_control_api.tsx b/src/platform/plugins/shared/controls/public/controls/initialize_default_control_api.tsx index 06d7f3e4028f5..77227e0c13eed 100644 --- a/src/platform/plugins/shared/controls/public/controls/initialize_default_control_api.tsx +++ b/src/platform/plugins/shared/controls/public/controls/initialize_default_control_api.tsx @@ -8,9 +8,7 @@ */ import { BehaviorSubject } from 'rxjs'; - -import { SerializedPanelState } from '@kbn/presentation-containers'; -import { StateComparators } from '@kbn/presentation-publishing'; +import { StateComparators, SerializedPanelState } from '@kbn/presentation-publishing'; import type { ControlWidth, DefaultControlState } from '../../common'; import type { ControlApiInitialization, ControlStateManager, DefaultControlApi } from './types'; diff --git a/src/platform/plugins/shared/controls/public/controls/timeslider_control/register_timeslider_control.ts b/src/platform/plugins/shared/controls/public/controls/timeslider_control/register_timeslider_control.ts index 93f30fe4b07d3..2937ec322b56f 100644 --- a/src/platform/plugins/shared/controls/public/controls/timeslider_control/register_timeslider_control.ts +++ b/src/platform/plugins/shared/controls/public/controls/timeslider_control/register_timeslider_control.ts @@ -14,7 +14,7 @@ import { registerControlFactory } from '../../control_factory_registry'; export function registerTimeSliderControl() { registerControlFactory(TIME_SLIDER_CONTROL, async () => { const [{ getTimesliderControlFactory }] = await Promise.all([ - import('./get_timeslider_control_factory'), + import('../../controls_module'), untilPluginStartServicesReady(), ]); return getTimesliderControlFactory(); diff --git a/src/platform/plugins/shared/controls/public/controls/types.ts b/src/platform/plugins/shared/controls/public/controls/types.ts index 8cc33b3513263..36b5ae6571169 100644 --- a/src/platform/plugins/shared/controls/public/controls/types.ts +++ b/src/platform/plugins/shared/controls/public/controls/types.ts @@ -9,12 +9,12 @@ import { BehaviorSubject } from 'rxjs'; -import { HasSerializableState } from '@kbn/presentation-containers'; import { PanelCompatibleComponent } from '@kbn/presentation-panel-plugin/public/panel_component/types'; import { HasParentApi, HasType, HasUniqueId, + HasSerializableState, PublishesBlockingError, PublishesDataLoading, PublishesDisabledActionIds, diff --git a/src/platform/plugins/shared/controls/public/controls_module.ts b/src/platform/plugins/shared/controls/public/controls_module.ts new file mode 100644 index 0000000000000..3dbcdf910cccb --- /dev/null +++ b/src/platform/plugins/shared/controls/public/controls_module.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export { ClearControlAction } from './actions/clear_control_action'; +export { DeleteControlAction } from './actions/delete_control_action'; +export { EditControlAction } from './actions/edit_control_action'; + +export { getControlGroupEmbeddableFactory } from './control_group/get_control_group_factory'; + +export { getOptionsListControlFactory } from './controls/data_controls/options_list_control/get_options_list_control_factory'; +export { getRangesliderControlFactory } from './controls/data_controls/range_slider/get_range_slider_control_factory'; +export { getTimesliderControlFactory } from './controls/timeslider_control/get_timeslider_control_factory'; + +export { ControlGroupRenderer } from './control_group/control_group_renderer/control_group_renderer'; diff --git a/src/platform/plugins/shared/controls/public/index.ts b/src/platform/plugins/shared/controls/public/index.ts index eaa800387759b..6455c71e7b5f6 100644 --- a/src/platform/plugins/shared/controls/public/index.ts +++ b/src/platform/plugins/shared/controls/public/index.ts @@ -14,9 +14,13 @@ export { type ControlGroupStateBuilder, } from './control_group/utils/control_group_state_builder'; -export type { ControlGroupApi, ControlStateTransform } from './control_group/types'; +export { + ACTION_CLEAR_CONTROL, + ACTION_DELETE_CONTROL, + ACTION_EDIT_CONTROL, +} from './actions/constants'; -export { ACTION_CLEAR_CONTROL, ACTION_DELETE_CONTROL, ACTION_EDIT_CONTROL } from './actions'; +export type { ControlGroupApi, ControlStateTransform } from './control_group/types'; export type { DataControlApi, DataControlFactory } from './controls/data_controls/types'; diff --git a/src/platform/plugins/shared/controls/public/plugin.ts b/src/platform/plugins/shared/controls/public/plugin.ts index 3e915e958d111..7c6d1ae91ab6a 100644 --- a/src/platform/plugins/shared/controls/public/plugin.ts +++ b/src/platform/plugins/shared/controls/public/plugin.ts @@ -8,17 +8,13 @@ */ import type { CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; -import { PANEL_HOVER_TRIGGER } from '@kbn/embeddable-plugin/public'; - -import { ClearControlAction } from './actions/clear_control_action'; -import { DeleteControlAction } from './actions/delete_control_action'; -import { EditControlAction } from './actions/edit_control_action'; import { registerControlGroupEmbeddable } from './control_group/register_control_group_embeddable'; import { registerOptionsListControl } from './controls/data_controls/options_list_control/register_options_list_control'; import { registerRangeSliderControl } from './controls/data_controls/range_slider/register_range_slider_control'; import { registerTimeSliderControl } from './controls/timeslider_control/register_timeslider_control'; -import { setKibanaServices, untilPluginStartServicesReady } from './services/kibana_services'; +import { setKibanaServices } from './services/kibana_services'; import type { ControlsPluginSetupDeps, ControlsPluginStartDeps } from './types'; +import { registerActions } from './actions/register_actions'; export class ControlsPlugin implements Plugin @@ -36,22 +32,9 @@ export class ControlsPlugin } public start(coreStart: CoreStart, startPlugins: ControlsPluginStartDeps) { - const { uiActions } = startPlugins; setKibanaServices(coreStart, startPlugins); - untilPluginStartServicesReady().then(() => { - const deleteControlAction = new DeleteControlAction(); - uiActions.registerAction(deleteControlAction); - uiActions.attachAction(PANEL_HOVER_TRIGGER, deleteControlAction.id); - - const editControlAction = new EditControlAction(); - uiActions.registerAction(editControlAction); - uiActions.attachAction(PANEL_HOVER_TRIGGER, editControlAction.id); - - const clearControlAction = new ClearControlAction(); - uiActions.registerAction(clearControlAction); - uiActions.attachAction(PANEL_HOVER_TRIGGER, clearControlAction.id); - }); + registerActions(startPlugins.uiActions); } public stop() {} diff --git a/src/platform/plugins/shared/controls/public/services/kibana_services.ts b/src/platform/plugins/shared/controls/public/services/kibana_services.ts index b9e5fadcecaa0..c13a56c3826ad 100644 --- a/src/platform/plugins/shared/controls/public/services/kibana_services.ts +++ b/src/platform/plugins/shared/controls/public/services/kibana_services.ts @@ -12,12 +12,14 @@ import { BehaviorSubject } from 'rxjs'; import { CoreStart } from '@kbn/core/public'; import { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; +import { UiActionsStart } from '@kbn/ui-actions-plugin/public'; import { ControlsPluginStartDeps } from '../types'; export let coreServices: CoreStart; export let dataService: DataPublicPluginStart; export let dataViewsService: DataViewsPublicPluginStart; +export let uiActionsService: UiActionsStart; const servicesReady$ = new BehaviorSubject(false); @@ -25,6 +27,7 @@ export const setKibanaServices = (kibanaCore: CoreStart, deps: ControlsPluginSta coreServices = kibanaCore; dataService = deps.data; dataViewsService = deps.dataViews; + uiActionsService = deps.uiActions; servicesReady$.next(true); }; diff --git a/src/platform/plugins/shared/dashboard/jest_setup.ts b/src/platform/plugins/shared/dashboard/jest_setup.ts index 1b0de7854d3ac..a86dc47ab043d 100644 --- a/src/platform/plugins/shared/dashboard/jest_setup.ts +++ b/src/platform/plugins/shared/dashboard/jest_setup.ts @@ -19,8 +19,10 @@ import { mockDashboardContentManagementCache, mockDashboardContentManagementService, setStubKibanaServices, + setStubLogger, } from './public/services/mocks'; +setStubLogger(); // Start the kibana services with stubs setStubKibanaServices(); diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_actions/actions_module.ts b/src/platform/plugins/shared/dashboard/public/dashboard_actions/actions_module.ts index 8747ff18f8f74..8b4c0154de18e 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_actions/actions_module.ts +++ b/src/platform/plugins/shared/dashboard/public/dashboard_actions/actions_module.ts @@ -11,8 +11,6 @@ export { ClonePanelAction } from './clone_panel_action'; export { ExpandPanelAction } from './expand_panel_action'; export { FiltersNotificationAction } from './filters_notification_action'; export { ExportCSVAction } from './export_csv_action'; -export { AddToLibraryAction } from './add_to_library_action'; -export { LegacyAddToLibraryAction } from './legacy_add_to_library_action'; +export { AddToLibraryAction } from './library_add_action'; +export { UnlinkFromLibraryAction } from './library_unlink_action'; export { CopyToDashboardAction } from './copy_to_dashboard_action'; -export { UnlinkFromLibraryAction } from './unlink_from_library_action'; -export { LegacyUnlinkFromLibraryAction } from './legacy_unlink_from_library_action'; diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_actions/clone_panel_action.test.tsx b/src/platform/plugins/shared/dashboard/public/dashboard_actions/clone_panel_action.test.tsx index e551fe78b4ac3..9f1063b4f5298 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_actions/clone_panel_action.test.tsx +++ b/src/platform/plugins/shared/dashboard/public/dashboard_actions/clone_panel_action.test.tsx @@ -21,6 +21,11 @@ describe('Clone panel action', () => { embeddable: { uuid: 'superId', viewMode: new BehaviorSubject('edit'), + serializeState: () => { + return { + rawState: {}, + }; + }, parentApi: { duplicatePanel: jest.fn(), }, diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_actions/clone_panel_action.tsx b/src/platform/plugins/shared/dashboard/public/dashboard_actions/clone_panel_action.tsx index 2f016c7fd872b..82a5b02059fd5 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_actions/clone_panel_action.tsx +++ b/src/platform/plugins/shared/dashboard/public/dashboard_actions/clone_panel_action.tsx @@ -17,6 +17,8 @@ import { getInheritedViewMode, HasParentApi, PublishesBlockingError, + apiHasSerializableState, + HasSerializableState, HasUniqueId, } from '@kbn/presentation-publishing'; import { Action, IncompatibleActionError } from '@kbn/ui-actions-plugin/public'; @@ -24,6 +26,7 @@ import { dashboardClonePanelActionStrings } from './_dashboard_actions_strings'; import { ACTION_CLONE_PANEL, DASHBOARD_ACTION_GROUP } from './constants'; export type ClonePanelActionApi = CanAccessViewMode & + HasSerializableState & HasUniqueId & HasParentApi & Partial; @@ -31,6 +34,7 @@ export type ClonePanelActionApi = CanAccessViewMode & const isApiCompatible = (api: unknown | null): api is ClonePanelActionApi => Boolean( apiHasUniqueId(api) && + apiHasSerializableState(api) && apiCanAccessViewMode(api) && apiHasParentApi(api) && apiCanDuplicatePanels(api.parentApi) diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_actions/constants.ts b/src/platform/plugins/shared/dashboard/public/dashboard_actions/constants.ts index 0135ed4f69a3c..33ae533e9f50a 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_actions/constants.ts +++ b/src/platform/plugins/shared/dashboard/public/dashboard_actions/constants.ts @@ -14,7 +14,5 @@ export const ACTION_CLONE_PANEL = 'clonePanel'; export const ACTION_COPY_TO_DASHBOARD = 'copyToDashboard'; export const ACTION_EXPAND_PANEL = 'togglePanel'; export const ACTION_EXPORT_CSV = 'ACTION_EXPORT_CSV'; -export const ACTION_LEGACY_ADD_TO_LIBRARY = 'legacySaveToLibrary'; -export const ACTION_LEGACY_UNLINK_FROM_LIBRARY = 'legacyUnlinkFromLibrary'; export const ACTION_UNLINK_FROM_LIBRARY = 'unlinkFromLibrary'; export const BADGE_FILTERS_NOTIFICATION = 'ACTION_FILTERS_NOTIFICATION'; diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_actions/copy_to_dashboard_modal.tsx b/src/platform/plugins/shared/dashboard/public/dashboard_actions/copy_to_dashboard_modal.tsx index 3c78088a7c098..9c04e0fff1e2c 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_actions/copy_to_dashboard_modal.tsx +++ b/src/platform/plugins/shared/dashboard/public/dashboard_actions/copy_to_dashboard_modal.tsx @@ -19,7 +19,7 @@ import { EuiSpacer, } from '@elastic/eui'; import { EmbeddablePackageState, PanelNotFoundError } from '@kbn/embeddable-plugin/public'; -import { apiHasSnapshottableState } from '@kbn/presentation-containers/interfaces/serialized_state'; +import { apiHasSnapshottableState } from '@kbn/presentation-publishing'; import { LazyDashboardPicker, withSuspense } from '@kbn/presentation-util-plugin/public'; import { omit } from 'lodash'; import React, { useCallback, useMemo, useState } from 'react'; diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_actions/legacy_add_to_library_action.test.tsx b/src/platform/plugins/shared/dashboard/public/dashboard_actions/legacy_add_to_library_action.test.tsx deleted file mode 100644 index 60367d7950d2e..0000000000000 --- a/src/platform/plugins/shared/dashboard/public/dashboard_actions/legacy_add_to_library_action.test.tsx +++ /dev/null @@ -1,79 +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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { PublishesViewMode, ViewMode } from '@kbn/presentation-publishing'; -import { BehaviorSubject } from 'rxjs'; -import { - LegacyAddToLibraryAction, - LegacyAddPanelToLibraryActionApi, -} from './legacy_add_to_library_action'; -import { coreServices } from '../services/kibana_services'; - -describe('Add to library action', () => { - let action: LegacyAddToLibraryAction; - let context: { embeddable: LegacyAddPanelToLibraryActionApi }; - - beforeEach(() => { - action = new LegacyAddToLibraryAction(); - context = { - embeddable: { - linkToLibrary: jest.fn(), - canLinkToLibrary: jest.fn().mockResolvedValue(true), - unlinkFromLibrary: jest.fn(), - canUnlinkFromLibrary: jest.fn().mockResolvedValue(true), - - viewMode: new BehaviorSubject('edit'), - panelTitle: new BehaviorSubject('A very compatible API'), - }, - }; - }); - - it('is compatible when api meets all conditions', async () => { - expect(await action.isCompatible(context)).toBe(true); - }); - - it('is incompatible when context lacks necessary functions', async () => { - const emptyContext = { - embeddable: {}, - }; - expect(await action.isCompatible(emptyContext)).toBe(false); - }); - - it('is incompatible when view mode is view', async () => { - (context.embeddable as PublishesViewMode).viewMode = new BehaviorSubject('view'); - expect(await action.isCompatible(context)).toBe(false); - }); - - it('is incompatible when canLinkToLibrary returns false', async () => { - context.embeddable.canLinkToLibrary = jest.fn().mockResolvedValue(false); - expect(await action.isCompatible(context)).toBe(false); - }); - - it('calls the linkToLibrary method on execute', async () => { - action.execute(context); - expect(context.embeddable.linkToLibrary).toHaveBeenCalled(); - }); - - it('shows a toast with a title from the API when successful', async () => { - await action.execute(context); - expect(coreServices.notifications.toasts.addSuccess).toHaveBeenCalledWith({ - 'data-test-subj': 'addPanelToLibrarySuccess', - title: "Panel 'A very compatible API' was added to the library", - }); - }); - - it('shows a danger toast when the link operation is unsuccessful', async () => { - context.embeddable.linkToLibrary = jest.fn().mockRejectedValue(new Error('Oh dang')); - await action.execute(context); - expect(coreServices.notifications.toasts.addDanger).toHaveBeenCalledWith({ - 'data-test-subj': 'addPanelToLibraryError', - title: 'An error was encountered adding panel A very compatible API to the library', - }); - }); -}); diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_actions/legacy_add_to_library_action.tsx b/src/platform/plugins/shared/dashboard/public/dashboard_actions/legacy_add_to_library_action.tsx deleted file mode 100644 index c263aafffad77..0000000000000 --- a/src/platform/plugins/shared/dashboard/public/dashboard_actions/legacy_add_to_library_action.tsx +++ /dev/null @@ -1,72 +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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { - apiCanAccessViewMode, - apiHasLegacyLibraryTransforms, - EmbeddableApiContext, - getPanelTitle, - PublishesPanelTitle, - CanAccessViewMode, - getInheritedViewMode, - HasLegacyLibraryTransforms, -} from '@kbn/presentation-publishing'; -import { Action, IncompatibleActionError } from '@kbn/ui-actions-plugin/public'; - -import { dashboardAddToLibraryActionStrings } from './_dashboard_actions_strings'; -import { coreServices } from '../services/kibana_services'; -import { ACTION_LEGACY_ADD_TO_LIBRARY, DASHBOARD_ACTION_GROUP } from './constants'; - -export type LegacyAddPanelToLibraryActionApi = CanAccessViewMode & - HasLegacyLibraryTransforms & - Partial; - -const isApiCompatible = (api: unknown | null): api is LegacyAddPanelToLibraryActionApi => - Boolean(apiCanAccessViewMode(api) && apiHasLegacyLibraryTransforms(api)); - -export class LegacyAddToLibraryAction implements Action { - public readonly type = ACTION_LEGACY_ADD_TO_LIBRARY; - public readonly id = ACTION_LEGACY_ADD_TO_LIBRARY; - public order = 15; - public grouping = [DASHBOARD_ACTION_GROUP]; - - public getDisplayName({ embeddable }: EmbeddableApiContext) { - if (!isApiCompatible(embeddable)) throw new IncompatibleActionError(); - return dashboardAddToLibraryActionStrings.getDisplayName(); - } - - public getIconType({ embeddable }: EmbeddableApiContext) { - if (!isApiCompatible(embeddable)) throw new IncompatibleActionError(); - return 'folderCheck'; - } - - public async isCompatible({ embeddable }: EmbeddableApiContext) { - if (!isApiCompatible(embeddable)) return false; - return getInheritedViewMode(embeddable) === 'edit' && (await embeddable.canLinkToLibrary()); - } - - public async execute({ embeddable }: EmbeddableApiContext) { - if (!isApiCompatible(embeddable)) throw new IncompatibleActionError(); - const panelTitle = getPanelTitle(embeddable); - try { - await embeddable.linkToLibrary(); - coreServices.notifications.toasts.addSuccess({ - title: dashboardAddToLibraryActionStrings.getSuccessMessage( - panelTitle ? `'${panelTitle}'` : '' - ), - 'data-test-subj': 'addPanelToLibrarySuccess', - }); - } catch (e) { - coreServices.notifications.toasts.addDanger({ - title: dashboardAddToLibraryActionStrings.getErrorMessage(panelTitle), - 'data-test-subj': 'addPanelToLibraryError', - }); - } - } -} diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_actions/legacy_unlink_from_library_action.test.tsx b/src/platform/plugins/shared/dashboard/public/dashboard_actions/legacy_unlink_from_library_action.test.tsx deleted file mode 100644 index 7a7e8836a305f..0000000000000 --- a/src/platform/plugins/shared/dashboard/public/dashboard_actions/legacy_unlink_from_library_action.test.tsx +++ /dev/null @@ -1,78 +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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { PublishesViewMode, ViewMode } from '@kbn/presentation-publishing'; -import { BehaviorSubject } from 'rxjs'; -import { coreServices } from '../services/kibana_services'; -import { - LegacyUnlinkFromLibraryAction, - LegacyUnlinkPanelFromLibraryActionApi, -} from './legacy_unlink_from_library_action'; - -describe('Unlink from library action', () => { - let action: LegacyUnlinkFromLibraryAction; - let context: { embeddable: LegacyUnlinkPanelFromLibraryActionApi }; - - beforeEach(() => { - action = new LegacyUnlinkFromLibraryAction(); - context = { - embeddable: { - unlinkFromLibrary: jest.fn(), - canUnlinkFromLibrary: jest.fn().mockResolvedValue(true), - linkToLibrary: jest.fn(), - canLinkToLibrary: jest.fn().mockResolvedValue(true), - viewMode: new BehaviorSubject('edit'), - panelTitle: new BehaviorSubject('A very compatible API'), - }, - }; - }); - - it('is compatible when api meets all conditions', async () => { - expect(await action.isCompatible(context)).toBe(true); - }); - - it('is incompatible when context lacks necessary functions', async () => { - const emptyContext = { - embeddable: {}, - }; - expect(await action.isCompatible(emptyContext)).toBe(false); - }); - - it('is incompatible when view mode is view', async () => { - (context.embeddable as PublishesViewMode).viewMode = new BehaviorSubject('view'); - expect(await action.isCompatible(context)).toBe(false); - }); - - it('is incompatible when canUnlinkFromLibrary returns false', async () => { - context.embeddable.canUnlinkFromLibrary = jest.fn().mockResolvedValue(false); - expect(await action.isCompatible(context)).toBe(false); - }); - - it('calls the unlinkFromLibrary method on execute', async () => { - action.execute(context); - expect(context.embeddable.unlinkFromLibrary).toHaveBeenCalled(); - }); - - it('shows a toast with a title from the API when successful', async () => { - await action.execute(context); - expect(coreServices.notifications.toasts.addSuccess).toHaveBeenCalledWith({ - 'data-test-subj': 'unlinkPanelSuccess', - title: "Panel 'A very compatible API' is no longer connected to the library.", - }); - }); - - it('shows a danger toast when the link operation is unsuccessful', async () => { - context.embeddable.unlinkFromLibrary = jest.fn().mockRejectedValue(new Error('Oh dang')); - await action.execute(context); - expect(coreServices.notifications.toasts.addDanger).toHaveBeenCalledWith({ - 'data-test-subj': 'unlinkPanelFailure', - title: "An error occured while unlinking 'A very compatible API' from the library.", - }); - }); -}); diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_actions/legacy_unlink_from_library_action.tsx b/src/platform/plugins/shared/dashboard/public/dashboard_actions/legacy_unlink_from_library_action.tsx deleted file mode 100644 index 9c37ee31a89a1..0000000000000 --- a/src/platform/plugins/shared/dashboard/public/dashboard_actions/legacy_unlink_from_library_action.tsx +++ /dev/null @@ -1,72 +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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { Action, IncompatibleActionError } from '@kbn/ui-actions-plugin/public'; - -import { - apiCanAccessViewMode, - apiHasLegacyLibraryTransforms, - CanAccessViewMode, - EmbeddableApiContext, - getInheritedViewMode, - getPanelTitle, - PublishesPanelTitle, - HasLegacyLibraryTransforms, -} from '@kbn/presentation-publishing'; -import { dashboardUnlinkFromLibraryActionStrings } from './_dashboard_actions_strings'; -import { coreServices } from '../services/kibana_services'; -import { ACTION_LEGACY_UNLINK_FROM_LIBRARY, DASHBOARD_ACTION_GROUP } from './constants'; - -export type LegacyUnlinkPanelFromLibraryActionApi = CanAccessViewMode & - HasLegacyLibraryTransforms & - Partial; - -export const legacyUnlinkActionIsCompatible = ( - api: unknown | null -): api is LegacyUnlinkPanelFromLibraryActionApi => - Boolean(apiCanAccessViewMode(api) && apiHasLegacyLibraryTransforms(api)); - -export class LegacyUnlinkFromLibraryAction implements Action { - public readonly type = ACTION_LEGACY_UNLINK_FROM_LIBRARY; - public readonly id = ACTION_LEGACY_UNLINK_FROM_LIBRARY; - public order = 15; - public grouping = [DASHBOARD_ACTION_GROUP]; - - public getDisplayName({ embeddable }: EmbeddableApiContext) { - if (!legacyUnlinkActionIsCompatible(embeddable)) throw new IncompatibleActionError(); - return dashboardUnlinkFromLibraryActionStrings.getDisplayName(); - } - - public getIconType({ embeddable }: EmbeddableApiContext) { - if (!legacyUnlinkActionIsCompatible(embeddable)) throw new IncompatibleActionError(); - return 'folderExclamation'; - } - - public async isCompatible({ embeddable }: EmbeddableApiContext) { - if (!legacyUnlinkActionIsCompatible(embeddable)) return false; - return getInheritedViewMode(embeddable) === 'edit' && (await embeddable.canUnlinkFromLibrary()); - } - - public async execute({ embeddable }: EmbeddableApiContext) { - if (!legacyUnlinkActionIsCompatible(embeddable)) throw new IncompatibleActionError(); - const title = getPanelTitle(embeddable); - try { - await embeddable.unlinkFromLibrary(); - coreServices.notifications.toasts.addSuccess({ - title: dashboardUnlinkFromLibraryActionStrings.getSuccessMessage(title ? `'${title}'` : ''), - 'data-test-subj': 'unlinkPanelSuccess', - }); - } catch (e) { - coreServices.notifications.toasts.addDanger({ - title: dashboardUnlinkFromLibraryActionStrings.getFailureMessage(title ? `'${title}'` : ''), - 'data-test-subj': 'unlinkPanelFailure', - }); - } - } -} diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_actions/add_to_library_action.tsx b/src/platform/plugins/shared/dashboard/public/dashboard_actions/library_add_action.tsx similarity index 68% rename from src/platform/plugins/shared/dashboard/public/dashboard_actions/add_to_library_action.tsx rename to src/platform/plugins/shared/dashboard/public/dashboard_actions/library_add_action.tsx index 28113d8fea92e..c74c1d45f2b54 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_actions/add_to_library_action.tsx +++ b/src/platform/plugins/shared/dashboard/public/dashboard_actions/library_add_action.tsx @@ -9,11 +9,10 @@ import React from 'react'; -import { PresentationContainer } from '@kbn/presentation-containers'; +import { PanelPackage, PresentationContainer } from '@kbn/presentation-containers'; import { CanAccessViewMode, EmbeddableApiContext, - HasInPlaceLibraryTransforms, HasLibraryTransforms, HasParentApi, HasType, @@ -21,7 +20,6 @@ import { HasUniqueId, PublishesPanelTitle, apiCanAccessViewMode, - apiHasInPlaceLibraryTransforms, apiHasLibraryTransforms, apiHasParentApi, apiHasType, @@ -44,14 +42,14 @@ import { ACTION_ADD_TO_LIBRARY, DASHBOARD_ACTION_GROUP } from './constants'; export type AddPanelToLibraryActionApi = CanAccessViewMode & HasType & HasUniqueId & - (HasLibraryTransforms | HasInPlaceLibraryTransforms) & + HasLibraryTransforms & HasParentApi> & Partial; const isApiCompatible = (api: unknown | null): api is AddPanelToLibraryActionApi => Boolean( apiCanAccessViewMode(api) && - (apiHasLibraryTransforms(api) || apiHasInPlaceLibraryTransforms(api)) && + apiHasLibraryTransforms(api) && apiHasType(api) && apiHasUniqueId(api) && apiHasParentApi(api) && @@ -76,27 +74,37 @@ export class AddToLibraryAction implements Action { public async isCompatible({ embeddable }: EmbeddableApiContext) { if (!isApiCompatible(embeddable)) return false; - return getInheritedViewMode(embeddable) === 'edit' && (await this.canLinkToLibrary(embeddable)); + return getInheritedViewMode(embeddable) === 'edit' && (await embeddable.canLinkToLibrary()); } public async execute({ embeddable }: EmbeddableApiContext) { if (!isApiCompatible(embeddable)) throw new IncompatibleActionError(); - const title = getPanelTitle(embeddable); - + const lastTitle = getPanelTitle(embeddable); try { - const byRefState = await new Promise((resolve, reject) => { - const onSave = async (props: OnSaveProps): Promise => { + const { byRefPackage, libraryTitle } = await new Promise<{ + byRefPackage: PanelPackage; + libraryTitle: string; + }>((resolve, reject) => { + const onSave = async ({ + newTitle, + isTitleDuplicateConfirmed, + onTitleDuplicate, + }: OnSaveProps): Promise => { await embeddable.checkForDuplicateTitle( - props.newTitle, - props.isTitleDuplicateConfirmed, - props.onTitleDuplicate + newTitle, + isTitleDuplicateConfirmed, + onTitleDuplicate ); try { - const libraryId = await embeddable.saveToLibrary(props.newTitle); - if (apiHasLibraryTransforms(embeddable)) { - resolve({ ...embeddable.getByReferenceState(libraryId), title: props.newTitle }); - } - resolve(undefined); + const libraryId = await embeddable.saveToLibrary(newTitle); + const { rawState, references } = embeddable.getSerializedStateByReference(libraryId); + resolve({ + byRefPackage: { + serializedState: { rawState: { ...rawState, title: newTitle }, references }, + panelType: embeddable.type, + }, + libraryTitle: newTitle, + }); return { id: libraryId }; } catch (error) { reject(error); @@ -107,7 +115,7 @@ export class AddToLibraryAction implements Action { {}} - title={title ?? ''} + title={lastTitle ?? ''} showCopyOnSave={false} objectType={ typeof embeddable.getTypeDisplayName === 'function' @@ -118,35 +126,17 @@ export class AddToLibraryAction implements Action { /> ); }); - /** - * If byRefState is defined, this embeddable type must be re-initialized with the - * newly provided state. - */ - if (byRefState) { - await embeddable.parentApi.replacePanel(embeddable.uuid, { - panelType: embeddable.type, - initialState: byRefState, - }); - } + + await embeddable.parentApi.replacePanel(embeddable.uuid, byRefPackage); coreServices.notifications.toasts.addSuccess({ - title: dashboardAddToLibraryActionStrings.getSuccessMessage(title ? `'${title}'` : ''), + title: dashboardAddToLibraryActionStrings.getSuccessMessage(`'${libraryTitle}'`), 'data-test-subj': 'addPanelToLibrarySuccess', }); } catch (e) { coreServices.notifications.toasts.addDanger({ - title: dashboardAddToLibraryActionStrings.getErrorMessage(title), + title: dashboardAddToLibraryActionStrings.getErrorMessage(lastTitle), 'data-test-subj': 'addPanelToLibraryError', }); } } - - private async canLinkToLibrary(api: AddPanelToLibraryActionApi) { - if (apiHasLibraryTransforms(api)) { - return api.canLinkToLibrary?.(); - } else if (apiHasInPlaceLibraryTransforms(api)) { - const canLink = api.canLinkToLibrary ? await api.canLinkToLibrary() : true; - return api.libraryId$.value === undefined && canLink; - } - throw new IncompatibleActionError(); - } } diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_actions/unlink_from_library_action.tsx b/src/platform/plugins/shared/dashboard/public/dashboard_actions/library_unlink_action.tsx similarity index 73% rename from src/platform/plugins/shared/dashboard/public/dashboard_actions/unlink_from_library_action.tsx rename to src/platform/plugins/shared/dashboard/public/dashboard_actions/library_unlink_action.tsx index 43ff33c2238e5..8c496d8374005 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_actions/unlink_from_library_action.tsx +++ b/src/platform/plugins/shared/dashboard/public/dashboard_actions/library_unlink_action.tsx @@ -11,14 +11,12 @@ import { PresentationContainer } from '@kbn/presentation-containers'; import { CanAccessViewMode, EmbeddableApiContext, - HasInPlaceLibraryTransforms, HasLibraryTransforms, HasParentApi, HasType, HasUniqueId, PublishesPanelTitle, apiCanAccessViewMode, - apiHasInPlaceLibraryTransforms, apiHasLibraryTransforms, apiHasParentApi, apiHasType, @@ -33,7 +31,7 @@ import { dashboardUnlinkFromLibraryActionStrings } from './_dashboard_actions_st import { ACTION_UNLINK_FROM_LIBRARY, DASHBOARD_ACTION_GROUP } from './constants'; export type UnlinkPanelFromLibraryActionApi = CanAccessViewMode & - (HasLibraryTransforms | HasInPlaceLibraryTransforms) & + HasLibraryTransforms & HasType & HasUniqueId & HasParentApi> & @@ -42,7 +40,7 @@ export type UnlinkPanelFromLibraryActionApi = CanAccessViewMode & export const isApiCompatible = (api: unknown | null): api is UnlinkPanelFromLibraryActionApi => Boolean( apiCanAccessViewMode(api) && - (apiHasLibraryTransforms(api) || apiHasInPlaceLibraryTransforms(api)) && + apiHasLibraryTransforms(api) && apiHasUniqueId(api) && apiHasType(api) && apiHasParentApi(api) && @@ -65,40 +63,23 @@ export class UnlinkFromLibraryAction implements Action { return 'folderExclamation'; } - public async canUnlinkFromLibrary(api: UnlinkPanelFromLibraryActionApi) { - if (apiHasLibraryTransforms(api)) { - return api.canUnlinkFromLibrary(); - } else if (apiHasInPlaceLibraryTransforms(api)) { - const canUnLink = api.canUnlinkFromLibrary ? await api.canUnlinkFromLibrary() : true; - return canUnLink && Boolean(api.libraryId$.value); - } - throw new IncompatibleActionError(); - } - public async isCompatible({ embeddable }: EmbeddableApiContext) { if (!isApiCompatible(embeddable)) { // either a an `unlinkFromLibrary` method or a `getByValueState` method is required return false; } - return ( - getInheritedViewMode(embeddable) === 'edit' && (await this.canUnlinkFromLibrary(embeddable)) - ); + return getInheritedViewMode(embeddable) === 'edit' && (await embeddable.canUnlinkFromLibrary()); } public async execute({ embeddable }: EmbeddableApiContext) { if (!isApiCompatible(embeddable)) throw new IncompatibleActionError(); const title = getPanelTitle(embeddable); try { - if (apiHasLibraryTransforms(embeddable)) { - await embeddable.parentApi.replacePanel(embeddable.uuid, { - panelType: embeddable.type, - initialState: { ...embeddable.getByValueState(), title }, - }); - } else if (apiHasInPlaceLibraryTransforms(embeddable)) { - embeddable.unlinkFromLibrary(); - } else { - throw new IncompatibleActionError(); - } + const { references, rawState } = embeddable.getSerializedStateByValue(); + await embeddable.parentApi.replacePanel(embeddable.uuid, { + panelType: embeddable.type, + serializedState: { rawState: { ...rawState, title }, references }, + }); coreServices.notifications.toasts.addSuccess({ title: dashboardUnlinkFromLibraryActionStrings.getSuccessMessage(title ? `'${title}'` : ''), 'data-test-subj': 'unlinkPanelSuccess', diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_actions/register_actions.ts b/src/platform/plugins/shared/dashboard/public/dashboard_actions/register_actions.ts index 48f5b8f93562a..8ac9e60dc704a 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_actions/register_actions.ts +++ b/src/platform/plugins/shared/dashboard/public/dashboard_actions/register_actions.ts @@ -15,8 +15,6 @@ import { ACTION_COPY_TO_DASHBOARD, ACTION_EXPAND_PANEL, ACTION_EXPORT_CSV, - ACTION_LEGACY_ADD_TO_LIBRARY, - ACTION_LEGACY_UNLINK_FROM_LIBRARY, ACTION_UNLINK_FROM_LIBRARY, BADGE_FILTERS_NOTIFICATION, } from './constants'; @@ -63,24 +61,12 @@ export const registerActions = async ({ }); uiActions.attachAction(CONTEXT_MENU_TRIGGER, ACTION_ADD_TO_LIBRARY); - uiActions.registerActionAsync(ACTION_LEGACY_ADD_TO_LIBRARY, async () => { - const { LegacyAddToLibraryAction } = await import('./actions_module'); - return new LegacyAddToLibraryAction(); - }); - uiActions.attachAction(CONTEXT_MENU_TRIGGER, ACTION_LEGACY_ADD_TO_LIBRARY); - uiActions.registerActionAsync(ACTION_UNLINK_FROM_LIBRARY, async () => { const { UnlinkFromLibraryAction } = await import('./actions_module'); return new UnlinkFromLibraryAction(); }); uiActions.attachAction(CONTEXT_MENU_TRIGGER, ACTION_UNLINK_FROM_LIBRARY); - uiActions.registerActionAsync(ACTION_LEGACY_UNLINK_FROM_LIBRARY, async () => { - const { LegacyUnlinkFromLibraryAction } = await import('./actions_module'); - return new LegacyUnlinkFromLibraryAction(); - }); - uiActions.attachAction(CONTEXT_MENU_TRIGGER, ACTION_LEGACY_UNLINK_FROM_LIBRARY); - uiActions.registerActionAsync(ACTION_COPY_TO_DASHBOARD, async () => { const { CopyToDashboardAction } = await import('./actions_module'); return new CopyToDashboardAction(); diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_api/get_dashboard_api.ts b/src/platform/plugins/shared/dashboard/public/dashboard_api/get_dashboard_api.ts index 4c92119b46733..2f6e680f77871 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_api/get_dashboard_api.ts +++ b/src/platform/plugins/shared/dashboard/public/dashboard_api/get_dashboard_api.ts @@ -7,23 +7,33 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { BehaviorSubject, debounceTime, merge } from 'rxjs'; -import { omit } from 'lodash'; -import { v4 } from 'uuid'; import type { Reference } from '@kbn/content-management-utils'; import { ControlGroupApi, ControlGroupSerializedState } from '@kbn/controls-plugin/public'; import { EmbeddablePackageState } from '@kbn/embeddable-plugin/public'; +import { StateComparators } from '@kbn/presentation-publishing'; +import { omit } from 'lodash'; +import { BehaviorSubject, debounceTime, merge } from 'rxjs'; +import { v4 } from 'uuid'; import { getReferencesForControls, getReferencesForPanelId, } from '../../common/dashboard_container/persistable_state/dashboard_container_references'; -import { initializeTrackPanel } from './track_panel'; -import { initializeTrackOverlay } from './track_overlay'; -import { initializeUnsavedChangesManager } from './unsaved_changes_manager'; +import { UnsavedPanelState } from '../dashboard_container/types'; import { DASHBOARD_APP_ID } from '../plugin_constants'; -import { DEFAULT_DASHBOARD_INPUT } from './default_dashboard_input'; +import { PANELS_CONTROL_GROUP_KEY } from '../services/dashboard_backup_service'; +import { getDashboardContentManagementService } from '../services/dashboard_content_management_service'; import { LoadDashboardReturn } from '../services/dashboard_content_management_service/types'; +import { initializeDataLoadingManager } from './data_loading_manager'; +import { initializeDataViewsManager } from './data_views_manager'; +import { DEFAULT_DASHBOARD_INPUT } from './default_dashboard_input'; +import { getSerializedState } from './get_serialized_state'; +import { openSaveModal } from './open_save_modal'; import { initializePanelsManager } from './panels_manager'; +import { initializeSearchSessionManager } from './search_session_manager'; +import { initializeSettingsManager } from './settings_manager'; +import { initializeTrackContentfulRender } from './track_contentful_render'; +import { initializeTrackOverlay } from './track_overlay'; +import { initializeTrackPanel } from './track_panel'; import { DASHBOARD_API_TYPE, DashboardApi, @@ -31,18 +41,9 @@ import { DashboardInternalApi, DashboardState, } from './types'; -import { initializeDataViewsManager } from './data_views_manager'; -import { initializeSettingsManager } from './settings_manager'; import { initializeUnifiedSearchManager } from './unified_search_manager'; -import { initializeDataLoadingManager } from './data_loading_manager'; -import { PANELS_CONTROL_GROUP_KEY } from '../services/dashboard_backup_service'; -import { getDashboardContentManagementService } from '../services/dashboard_content_management_service'; -import { openSaveModal } from './open_save_modal'; -import { initializeSearchSessionManager } from './search_session_manager'; +import { initializeUnsavedChangesManager } from './unsaved_changes_manager'; import { initializeViewModeManager } from './view_mode_manager'; -import { UnsavedPanelState } from '../dashboard_container/types'; -import { initializeTrackContentfulRender } from './track_contentful_render'; -import { getSerializedState } from './get_serialized_state'; export function getDashboardApi({ creationOptions, @@ -62,26 +63,34 @@ export function getDashboardApi({ const controlGroupApi$ = new BehaviorSubject(undefined); const fullScreenMode$ = new BehaviorSubject(creationOptions?.fullScreenMode ?? false); const isManaged = savedObjectResult?.managed ?? false; - let references: Reference[] = savedObjectResult?.references ?? []; const savedObjectId$ = new BehaviorSubject(savedObjectId); const viewModeManager = initializeViewModeManager(incomingEmbeddable, savedObjectResult); const trackPanel = initializeTrackPanel( async (id: string) => await panelsManager.api.untilEmbeddableLoaded(id) ); - function getPanelReferences(id: string) { - const panelReferences = getReferencesForPanelId(id, references); + + const references$ = new BehaviorSubject(initialState.references); + const getPanelReferences = (id: string) => { + const panelReferences = getReferencesForPanelId(id, references$.value ?? []); // references from old installations may not be prefixed with panel id // fall back to passing all references in these cases to preserve backwards compatability - return panelReferences.length > 0 ? panelReferences : references; - } + return panelReferences.length > 0 ? panelReferences : references$.value ?? []; + }; + const pushPanelReferences = (refs: Reference[]) => { + references$.next([...(references$.value ?? []), ...refs]); + }; + const referencesComparator: StateComparators> = { + references: [references$, (nextRefs) => references$.next(nextRefs)], + }; + const panelsManager = initializePanelsManager( incomingEmbeddable, initialState.panels, initialPanelsRuntimeState ?? {}, trackPanel, getPanelReferences, - (refs: Reference[]) => references.push(...refs) + pushPanelReferences ); const dataLoadingManager = initializeDataLoadingManager(panelsManager.api.children$); const dataViewsManager = initializeDataViewsManager( @@ -108,6 +117,7 @@ export function getDashboardApi({ settingsManager, viewModeManager, unifiedSearchManager, + referencesComparator, }); function getState() { const { panels, references: panelReferences } = panelsManager.internalApi.getState(); @@ -192,7 +202,7 @@ export function getDashboardApi({ }); savedObjectId$.next(saveResult.id); - references = saveResult.references ?? []; + references$.next(saveResult.references); } return saveResult; @@ -211,7 +221,7 @@ export function getDashboardApi({ }); unsavedChangesManager.internalApi.onSave(dashboardState); - references = saveResult.references ?? []; + references$.next(saveResult.references); return; }, @@ -253,7 +263,7 @@ export function getDashboardApi({ labelPosition: 'oneLine', showApplySelections: false, } as ControlGroupSerializedState), - references: getReferencesForControls(references), + references: getReferencesForControls(references$.value ?? []), }; }, getRuntimeStateForControlGroup: () => { diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_api/load_dashboard_api.ts b/src/platform/plugins/shared/dashboard/public/dashboard_api/load_dashboard_api.ts index 0bd2da734ba8d..c1c08cbd8177b 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_api/load_dashboard_api.ts +++ b/src/platform/plugins/shared/dashboard/public/dashboard_api/load_dashboard_api.ts @@ -14,6 +14,7 @@ import { DashboardCreationOptions, DashboardState } from './types'; import { getDashboardApi } from './get_dashboard_api'; import { startQueryPerformanceTracking } from '../dashboard_container/embeddable/create/performance/query_performance_tracking'; import { coreServices } from '../services/kibana_services'; +import { logger } from '../services/logger'; import { PANELS_CONTROL_GROUP_KEY, getDashboardBackupService, @@ -65,6 +66,9 @@ export async function loadDashboardApi({ ...(savedObjectResult?.dashboardInput ?? {}), ...sessionStorageInput, }; + combinedSessionState.references = sessionStorageInput?.references?.length + ? sessionStorageInput?.references + : savedObjectResult?.references; // -------------------------------------------------------------------------------------- // Combine state with overrides. @@ -123,7 +127,7 @@ export async function loadDashboardApi({ // however, there is an edge case that we now count a new view when a user is editing a dashboard and is returning from an editor by canceling // TODO: this should be revisited by making embeddable transfer support canceling logic https://github.com/elastic/kibana/issues/190485 const contentInsightsClient = new ContentInsightsClient( - { http: coreServices.http }, + { http: coreServices.http, logger }, { domainId: 'dashboard' } ); contentInsightsClient.track(savedObjectId, 'viewed'); diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_api/panels_manager.ts b/src/platform/plugins/shared/dashboard/public/dashboard_api/panels_manager.ts index d2b1c0117214c..fc313cea93c85 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_api/panels_manager.ts +++ b/src/platform/plugins/shared/dashboard/public/dashboard_api/panels_manager.ts @@ -13,7 +13,7 @@ import { v4 } from 'uuid'; import { asyncForEach } from '@kbn/std'; import type { Reference } from '@kbn/content-management-utils'; import { METRIC_TYPE } from '@kbn/analytics'; -import { PanelPackage, apiHasSerializableState } from '@kbn/presentation-containers'; +import { PanelPackage } from '@kbn/presentation-containers'; import { DefaultEmbeddableApi, EmbeddablePackageState, @@ -21,14 +21,12 @@ import { } from '@kbn/embeddable-plugin/public'; import { StateComparators, - apiHasInPlaceLibraryTransforms, apiHasLibraryTransforms, apiPublishesPanelTitle, apiPublishesUnsavedChanges, + apiHasSerializableState, getPanelTitle, - stateHasTitles, } from '@kbn/presentation-publishing'; -import { apiHasSnapshottableState } from '@kbn/presentation-containers/interfaces/serialized_state'; import { i18n } from '@kbn/i18n'; import { coreServices, usageCollectionService } from '../services/kibana_services'; import { DashboardPanelMap, DashboardPanelState, prefixReferencesFromPanel } from '../../common'; @@ -171,72 +169,22 @@ export function initializePanelsManager( return titles; } - function duplicateReactEmbeddableInput( - childApi: unknown, - panelToClone: DashboardPanelState, - panelTitles: string[] - ) { - const id = v4(); - const lastTitle = apiPublishesPanelTitle(childApi) ? getPanelTitle(childApi) ?? '' : ''; - const newTitle = getClonedPanelTitle(panelTitles, lastTitle); - - /** - * For react embeddables that have library transforms, we need to ensure - * to clone them with serialized state and references. - * - * TODO: remove this section once all by reference capable react embeddables - * use in-place library transforms - */ - if (apiHasLibraryTransforms(childApi)) { - const byValueSerializedState = childApi.getByValueState(); - if (panelToClone.references) { - pushReferences(prefixReferencesFromPanel(id, panelToClone.references)); - } - return { - type: panelToClone.type, - explicitInput: { - ...byValueSerializedState, - title: newTitle, - id, - }, - }; - } - - const runtimeSnapshot = (() => { - if (apiHasInPlaceLibraryTransforms(childApi)) return childApi.getByValueRuntimeSnapshot(); - return apiHasSnapshottableState(childApi) ? childApi.snapshotRuntimeState() : {}; - })(); - if (stateHasTitles(runtimeSnapshot)) runtimeSnapshot.title = newTitle; - - setRuntimeStateForChild(id, runtimeSnapshot); - return { - type: panelToClone.type, - explicitInput: { - id, - }, - }; - } - return { api: { addNewPanel: async ( panelPackage: PanelPackage, displaySuccessMessage?: boolean ) => { - usageCollectionService?.reportUiCounter( - DASHBOARD_UI_METRIC_ID, - METRIC_TYPE.CLICK, - panelPackage.panelType - ); + const { panelType: type, serializedState, initialState } = panelPackage; + + usageCollectionService?.reportUiCounter(DASHBOARD_UI_METRIC_ID, METRIC_TYPE.CLICK, type); const newId = v4(); - const getCustomPlacementSettingFunc = getDashboardPanelPlacementSetting( - panelPackage.panelType - ); + const getCustomPlacementSettingFunc = getDashboardPanelPlacementSetting(type); const customPlacementSettings = getCustomPlacementSettingFunc - ? await getCustomPlacementSettingFunc(panelPackage.initialState) + ? await getCustomPlacementSettingFunc(initialState) : undefined; const { newPanelPlacement, otherPanels } = runPanelPlacementStrategy( @@ -247,19 +195,23 @@ export function initializePanelsManager( width: customPlacementSettings?.width ?? DEFAULT_PANEL_WIDTH, } ); + + if (serializedState?.references && serializedState.references.length > 0) { + pushReferences(prefixReferencesFromPanel(newId, serializedState.references)); + } const newPanel: DashboardPanelState = { - type: panelPackage.panelType, + type, gridData: { ...newPanelPlacement, i: newId, }, explicitInput: { + ...serializedState?.rawState, id: newId, }, }; - if (panelPackage.initialState) { - setRuntimeStateForChild(newId, panelPackage.initialState); - } + if (initialState) setRuntimeStateForChild(newId, initialState); + setPanels({ ...otherPanels, [newId]: newPanel }); if (displaySuccessMessage) { coreServices.notifications.toasts.addSuccess({ @@ -275,12 +227,27 @@ export function initializePanelsManager( children$, duplicatePanel: async (idToDuplicate: string) => { const panelToClone = getDashboardPanelFromId(idToDuplicate); + const childApi = children$.value[idToDuplicate]; + if (!apiHasSerializableState(childApi)) { + throw new Error('cannot duplicate a non-serializable panel'); + } - const duplicatedPanelState = duplicateReactEmbeddableInput( - children$.value[idToDuplicate], - panelToClone, - await getPanelTitles() - ); + const id = v4(); + const allPanelTitles = await getPanelTitles(); + const lastTitle = apiPublishesPanelTitle(childApi) ? getPanelTitle(childApi) ?? '' : ''; + const newTitle = getClonedPanelTitle(allPanelTitles, lastTitle); + + /** + * For embeddables that have library transforms, we need to ensure + * to clone them with by value serialized state. + */ + const serializedState = apiHasLibraryTransforms(childApi) + ? childApi.getSerializedStateByValue() + : childApi.serializeState(); + + if (serializedState.references) { + pushReferences(prefixReferencesFromPanel(id, serializedState.references)); + } coreServices.notifications.toasts.addSuccess({ title: dashboardClonePanelActionStrings.getSuccessMessage(), @@ -295,16 +262,21 @@ export function initializePanelsManager( }); const newPanel = { - ...duplicatedPanelState, + type: panelToClone.type, + explicitInput: { + ...serializedState.rawState, + title: newTitle, + id, + }, gridData: { ...newPanelPlacement, - i: duplicatedPanelState.explicitInput.id, + i: id, }, }; setPanels({ ...otherPanels, - [newPanel.explicitInput.id]: newPanel, + [id]: newPanel, }); }, getDashboardPanelFromId, @@ -337,7 +309,7 @@ export function initializePanelsManager( children$.next(children); } }, - replacePanel: async (idToRemove: string, { panelType, initialState }: PanelPackage) => { + replacePanel: async (idToRemove: string, panelPackage: PanelPackage) => { const panels = { ...panels$.value }; if (!panels[idToRemove]) { throw new PanelNotFoundError(); @@ -346,12 +318,20 @@ export function initializePanelsManager( const id = v4(); const oldPanel = panels[idToRemove]; delete panels[idToRemove]; + + const { panelType: type, serializedState, initialState } = panelPackage; + if (serializedState?.references && serializedState.references.length > 0) { + pushReferences(prefixReferencesFromPanel(id, serializedState?.references)); + } + + if (initialState) setRuntimeStateForChild(id, initialState); + setPanels({ ...panels, [id]: { ...oldPanel, - explicitInput: { ...initialState, id }, - type: panelType, + explicitInput: { ...serializedState?.rawState, id }, + type, }, }); diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_api/types.ts b/src/platform/plugins/shared/dashboard/public/dashboard_api/types.ts index 0318456ac0a0d..8b5c23bdf9bf2 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_api/types.ts +++ b/src/platform/plugins/shared/dashboard/public/dashboard_api/types.ts @@ -7,6 +7,16 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ +import type { Reference } from '@kbn/content-management-utils'; +import { + ControlGroupApi, + ControlGroupRuntimeState, + ControlGroupSerializedState, +} from '@kbn/controls-plugin/public'; +import { RefreshInterval, SearchSessionInfoProvider } from '@kbn/data-plugin/public'; +import type { DefaultEmbeddableApi, EmbeddablePackageState } from '@kbn/embeddable-plugin/public'; +import { Filter, Query, TimeRange } from '@kbn/es-query'; +import { IKbnUrlStateStorage } from '@kbn/kibana-utils-plugin/public'; import { CanExpandPanels, HasRuntimeChildState, @@ -14,11 +24,11 @@ import { HasSerializedChildState, PresentationContainer, PublishesSettings, - SerializedPanelState, TrackContentfulRender, TracksOverlays, } from '@kbn/presentation-containers'; import { + SerializedPanelState, EmbeddableAppContext, HasAppContext, HasExecutionContext, @@ -35,27 +45,17 @@ import { PublishingSubject, ViewMode, } from '@kbn/presentation-publishing'; -import { - ControlGroupApi, - ControlGroupRuntimeState, - ControlGroupSerializedState, -} from '@kbn/controls-plugin/public'; -import { Filter, Query, TimeRange } from '@kbn/es-query'; -import type { DefaultEmbeddableApi, EmbeddablePackageState } from '@kbn/embeddable-plugin/public'; -import { Observable, Subject } from 'rxjs'; -import { RefreshInterval, SearchSessionInfoProvider } from '@kbn/data-plugin/public'; -import { IKbnUrlStateStorage } from '@kbn/kibana-utils-plugin/public'; import { PublishesReload } from '@kbn/presentation-publishing/interfaces/fetch/publishes_reload'; import { PublishesSearchSession } from '@kbn/presentation-publishing/interfaces/fetch/publishes_search_session'; import { LocatorPublic } from '@kbn/share-plugin/common'; -import type { SavedObjectReference } from '@kbn/core-saved-objects-api-server'; +import { Observable, Subject } from 'rxjs'; import { DashboardPanelMap, DashboardPanelState } from '../../common'; import type { DashboardAttributes, DashboardOptions } from '../../server/content_management'; +import { DashboardLocatorParams } from '../dashboard_container/types'; import { LoadDashboardReturn, SaveDashboardReturn, } from '../services/dashboard_content_management_service/types'; -import { DashboardLocatorParams } from '../dashboard_container/types'; export const DASHBOARD_API_TYPE = 'dashboard'; @@ -101,6 +101,12 @@ export interface DashboardState extends DashboardSettings { viewMode: ViewMode; panels: DashboardPanelMap; + /** + * Temporary. Currently Dashboards are in charge of providing references to all of their children. + * Eventually this will be removed in favour of the Dashboard injecting references serverside. + */ + references?: Reference[]; + /** * Serialized control group state. * Contains state loaded from dashboard saved object @@ -145,7 +151,7 @@ export type DashboardApi = CanExpandPanels & getSettings: () => DashboardSettings; getSerializedState: () => { attributes: DashboardAttributes; - references: SavedObjectReference[]; + references: Reference[]; }; getDashboardPanelFromId: (id: string) => DashboardPanelState; hasOverlays$: PublishingSubject; diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_api/unsaved_changes_manager.ts b/src/platform/plugins/shared/dashboard/public/dashboard_api/unsaved_changes_manager.ts index 46ae02de87fc2..fef1175916a03 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_api/unsaved_changes_manager.ts +++ b/src/platform/plugins/shared/dashboard/public/dashboard_api/unsaved_changes_manager.ts @@ -7,19 +7,23 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { BehaviorSubject, Subject, combineLatest, debounceTime, skipWhile, switchMap } from 'rxjs'; -import { PublishesSavedObjectId, PublishingSubject } from '@kbn/presentation-publishing'; import { ControlGroupApi } from '@kbn/controls-plugin/public'; import { childrenUnsavedChanges$, initializeUnsavedChanges } from '@kbn/presentation-containers'; +import { + PublishesSavedObjectId, + PublishingSubject, + StateComparators, +} from '@kbn/presentation-publishing'; import { omit } from 'lodash'; -import { DashboardCreationOptions, DashboardState } from './types'; -import { initializePanelsManager } from './panels_manager'; -import { initializeSettingsManager } from './settings_manager'; -import { initializeUnifiedSearchManager } from './unified_search_manager'; +import { BehaviorSubject, Subject, combineLatest, debounceTime, skipWhile, switchMap } from 'rxjs'; import { PANELS_CONTROL_GROUP_KEY, getDashboardBackupService, } from '../services/dashboard_backup_service'; +import { initializePanelsManager } from './panels_manager'; +import { initializeSettingsManager } from './settings_manager'; +import { DashboardCreationOptions, DashboardState } from './types'; +import { initializeUnifiedSearchManager } from './unified_search_manager'; import { initializeViewModeManager } from './view_mode_manager'; export function initializeUnsavedChangesManager({ @@ -31,6 +35,7 @@ export function initializeUnsavedChangesManager({ settingsManager, viewModeManager, unifiedSearchManager, + referencesComparator, }: { creationOptions?: DashboardCreationOptions; controlGroupApi$: PublishingSubject; @@ -40,6 +45,7 @@ export function initializeUnsavedChangesManager({ settingsManager: ReturnType; viewModeManager: ReturnType; unifiedSearchManager: ReturnType; + referencesComparator: StateComparators>; }) { const hasUnsavedChanges$ = new BehaviorSubject(false); const lastSavedState$ = new BehaviorSubject(lastSavedState); @@ -55,6 +61,7 @@ export function initializeUnsavedChangesManager({ ...settingsManager.comparators, ...viewModeManager.comparators, ...unifiedSearchManager.comparators, + ...referencesComparator, } ); @@ -70,12 +77,14 @@ export function initializeUnsavedChangesManager({ ]) .pipe(debounceTime(0)) .subscribe(([dashboardChanges, unsavedPanelState, controlGroupChanges]) => { - // viewMode needs to be stored in session state because - // its used to exclude 'view' dashboards on the listing page - // However, viewMode should not trigger unsaved changes notification - // otherwise, opening a dashboard in edit mode will always show unsaved changes + /** + * viewMode needs to be stored in session state because its used to exclude 'view' dashboards on the listing page + * However, viewMode differences should not trigger unsaved changes notification otherwise, opening a dashboard in + * edit mode will always show unsaved changes. Similarly, differences in references are derived from panels, so + * we don't consider them unsaved changes + */ const hasDashboardChanges = - Object.keys(omit(dashboardChanges ?? {}, ['viewMode'])).length > 0; + Object.keys(omit(dashboardChanges ?? {}, ['viewMode', 'references'])).length > 0; const hasUnsavedChanges = hasDashboardChanges || unsavedPanelState !== undefined || controlGroupChanges !== undefined; if (hasUnsavedChanges !== hasUnsavedChanges$.value) { diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.tsx b/src/platform/plugins/shared/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.tsx index d7b72263bb93f..3422cd23c67c1 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.tsx +++ b/src/platform/plugins/shared/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.tsx @@ -26,6 +26,7 @@ import { getDashboardBackupService } from '../../services/dashboard_backup_servi import { getDashboardContentManagementService } from '../../services/dashboard_content_management_service'; import { getDashboardRecentlyAccessedService } from '../../services/dashboard_recently_accessed_service'; import { coreServices } from '../../services/kibana_services'; +import { logger } from '../../services/logger'; import { getDashboardCapabilities } from '../../utils/get_dashboard_capabilities'; import { dashboardListingErrorStrings, @@ -341,7 +342,7 @@ export const useDashboardListingTable = ({ ); const contentInsightsClient = useMemo( - () => new ContentInsightsClient({ http: coreServices.http }, { domainId: 'dashboard' }), + () => new ContentInsightsClient({ http: coreServices.http, logger }, { domainId: 'dashboard' }), [] ); diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_top_nav/internal_dashboard_top_nav.tsx b/src/platform/plugins/shared/dashboard/public/dashboard_top_nav/internal_dashboard_top_nav.tsx index 71f28d94fe2d3..7cb39231e814a 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_top_nav/internal_dashboard_top_nav.tsx +++ b/src/platform/plugins/shared/dashboard/public/dashboard_top_nav/internal_dashboard_top_nav.tsx @@ -118,6 +118,13 @@ export function InternalDashboardTopNav({ dashboardTitleRef.current?.focus(); }, [title, viewMode]); + /* + * Manage chrome visibility when dashboard is in print mode. + */ + useEffect(() => { + if (!embedSettings && viewMode === 'print') coreServices.chrome.setIsVisible(false); + }, [embedSettings, viewMode]); + /** * populate recently accessed, and set is chrome visible. */ diff --git a/src/platform/plugins/shared/dashboard/public/plugin.tsx b/src/platform/plugins/shared/dashboard/public/plugin.tsx index 2755c443ca083..caa8eec5d770f 100644 --- a/src/platform/plugins/shared/dashboard/public/plugin.tsx +++ b/src/platform/plugins/shared/dashboard/public/plugin.tsx @@ -79,6 +79,7 @@ import { } from './dashboard_container/panel_placement'; import type { FindDashboardsService } from './services/dashboard_content_management_service/types'; import { setKibanaServices, untilPluginStartServicesReady } from './services/kibana_services'; +import { setLogger } from './services/logger'; import { registerActions } from './dashboard_actions/register_actions'; export interface DashboardFeatureFlagConfig { @@ -156,7 +157,9 @@ export class DashboardPlugin implements Plugin { - constructor(private initializerContext: PluginInitializerContext) {} + constructor(private initializerContext: PluginInitializerContext) { + setLogger(initializerContext.logger.get('dashboard')); + } private appStateUpdater = new BehaviorSubject(() => ({})); private stopUrlTracking: (() => void) | undefined = undefined; diff --git a/src/platform/plugins/shared/dashboard/public/services/dashboard_backup_service.ts b/src/platform/plugins/shared/dashboard/public/services/dashboard_backup_service.ts index 30930e4970be2..584f615566243 100644 --- a/src/platform/plugins/shared/dashboard/public/services/dashboard_backup_service.ts +++ b/src/platform/plugins/shared/dashboard/public/services/dashboard_backup_service.ts @@ -176,7 +176,7 @@ class DashboardBackupService implements DashboardBackupServiceType { if ( dashboardStatesInSpace[dashboardId].viewMode === 'edit' && (Object.keys(dashboardStatesInSpace[dashboardId]).some( - (stateKey) => stateKey !== 'viewMode' + (stateKey) => stateKey !== 'viewMode' && stateKey !== 'references' ) || Object.keys(panelStatesInSpace?.[dashboardId]).length > 0) ) diff --git a/src/platform/plugins/shared/dashboard/public/services/logger.ts b/src/platform/plugins/shared/dashboard/public/services/logger.ts new file mode 100644 index 0000000000000..46bdfcab5000f --- /dev/null +++ b/src/platform/plugins/shared/dashboard/public/services/logger.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { Logger } from '@kbn/logging'; + +export let logger: Logger; + +export const setLogger = (_logger: Logger) => { + logger = _logger; +}; diff --git a/src/platform/plugins/shared/dashboard/public/services/mocks.ts b/src/platform/plugins/shared/dashboard/public/services/mocks.ts index c39c665ed55da..57ed1a4d0ce61 100644 --- a/src/platform/plugins/shared/dashboard/public/services/mocks.ts +++ b/src/platform/plugins/shared/dashboard/public/services/mocks.ts @@ -32,6 +32,7 @@ import { urlForwardingPluginMock } from '@kbn/url-forwarding-plugin/public/mocks import { visualizationsPluginMock } from '@kbn/visualizations-plugin/public/mocks'; import { setKibanaServices } from './kibana_services'; +import { setLogger } from './logger'; import { DashboardAttributes } from '../../server/content_management'; import { DashboardCapabilities } from '../../common'; import { LoadDashboardReturn } from './dashboard_content_management_service/types'; @@ -76,6 +77,10 @@ export const setStubKibanaServices = () => { }); }; +export const setStubLogger = () => { + setLogger(coreMock.createCoreContext().logger); +}; + export const mockDashboardContentManagementService = { loadDashboardState: jest.fn().mockImplementation(() => Promise.resolve({ diff --git a/src/platform/plugins/shared/data/public/query/timefilter/types.ts b/src/platform/plugins/shared/data/public/query/timefilter/types.ts index f07b01abfe2ac..a28609cfc5891 100644 --- a/src/platform/plugins/shared/data/public/query/timefilter/types.ts +++ b/src/platform/plugins/shared/data/public/query/timefilter/types.ts @@ -22,8 +22,8 @@ export interface TimefilterConfig { export type InputTimeRange = | TimeRange | { - from: Moment; - to: Moment; + from: Moment | string; + to: Moment | string; }; export type { TimeRangeBounds } from '../../../common'; diff --git a/src/platform/plugins/shared/data/server/config.ts b/src/platform/plugins/shared/data/server/config.ts index 71460d6a4c293..2df10db015671 100644 --- a/src/platform/plugins/shared/data/server/config.ts +++ b/src/platform/plugins/shared/data/server/config.ts @@ -13,7 +13,7 @@ export const searchSessionsConfigSchema = schema.object({ /** * Turns the feature on \ off (incl. removing indicator and management screens) */ - enabled: schema.boolean({ defaultValue: true }), + enabled: schema.boolean({ defaultValue: false }), /** * notTouchedTimeout controls how long user can save a session after all searches completed. diff --git a/src/platform/plugins/shared/data_view_field_editor/public/components/field_format_editor/editors/color/__snapshots__/color.test.tsx.snap b/src/platform/plugins/shared/data_view_field_editor/public/components/field_format_editor/editors/color/__snapshots__/color.test.tsx.snap index c0caa836b45c7..fbd82abc27e88 100644 --- a/src/platform/plugins/shared/data_view_field_editor/public/components/field_format_editor/editors/color/__snapshots__/color.test.tsx.snap +++ b/src/platform/plugins/shared/data_view_field_editor/public/components/field_format_editor/editors/color/__snapshots__/color.test.tsx.snap @@ -2,78 +2,41 @@ exports[`ColorFormatEditor should render boolean type normally 1`] = ` - , - "render": [Function], - }, - Object { - "field": "text", - "name": , - "render": [Function], - }, - Object { - "field": "background", - "name": , - "render": [Function], - }, - Object { - "name": , - "render": [Function], - }, - Object { - "actions": Array [ - Object { - "available": [Function], - "color": "danger", - "data-test-subj": "colorEditorRemoveColor", - "description": "Delete color format", - "icon": "trash", - "name": "Delete", - "onClick": [Function], - "type": "icon", - }, - ], - "field": "actions", - "name": "Actions", - }, - ] - } - items={ - Array [ + + + +

+ +

+
+ ", "text": "#000000", - }, - ] - } - noItemsMessage={ - - } - tableLayout="fixed" - /> + } + } + fieldType="boolean" + index={0} + key="0" + onColorChange={[Function]} + onRemoveColor={[Function]} + showDeleteButton={false} + /> +
@@ -96,86 +59,58 @@ exports[`ColorFormatEditor should render boolean type normally 1`] = ` exports[`ColorFormatEditor should render multiple colors 1`] = ` - , - "render": [Function], - }, - Object { - "field": "text", - "name": , - "render": [Function], - }, - Object { - "field": "background", - "name": , - "render": [Function], - }, - Object { - "name": , - "render": [Function], - }, - Object { - "actions": Array [ - Object { - "available": [Function], - "color": "danger", - "data-test-subj": "colorEditorRemoveColor", - "description": "Delete color format", - "icon": "trash", - "name": "Delete", - "onClick": [Function], - "type": "icon", - }, - ], - "field": "actions", - "name": "Actions", - }, - ] - } - items={ - Array [ + + + +

+ +

+
+ ", "text": "#000000", - }, + } + } + fieldType="string" + index={0} + key="0" + onColorChange={[Function]} + onRemoveColor={[Function]} + showDeleteButton={true} + /> + ", "text": "#000000", - }, - ] - } - noItemsMessage={ - - } - tableLayout="fixed" - /> + } + } + fieldType="string" + index={1} + key="1" + onColorChange={[Function]} + onRemoveColor={[Function]} + showDeleteButton={true} + /> +
@@ -198,78 +133,41 @@ exports[`ColorFormatEditor should render multiple colors 1`] = ` exports[`ColorFormatEditor should render other type normally (range field) 1`] = ` - , - "render": [Function], - }, - Object { - "field": "text", - "name": , - "render": [Function], - }, - Object { - "field": "background", - "name": , - "render": [Function], - }, - Object { - "name": , - "render": [Function], - }, - Object { - "actions": Array [ - Object { - "available": [Function], - "color": "danger", - "data-test-subj": "colorEditorRemoveColor", - "description": "Delete color format", - "icon": "trash", - "name": "Delete", - "onClick": [Function], - "type": "icon", - }, - ], - "field": "actions", - "name": "Actions", - }, - ] - } - items={ - Array [ + + + +

+ +

+
+ ", "text": "#000000", - }, - ] - } - noItemsMessage={ - - } - tableLayout="fixed" - /> + } + } + fieldType="number" + index={0} + key="0" + onColorChange={[Function]} + onRemoveColor={[Function]} + showDeleteButton={false} + /> +
@@ -292,78 +190,41 @@ exports[`ColorFormatEditor should render other type normally (range field) 1`] = exports[`ColorFormatEditor should render string type normally (regex field) 1`] = ` - , - "render": [Function], - }, - Object { - "field": "text", - "name": , - "render": [Function], - }, - Object { - "field": "background", - "name": , - "render": [Function], - }, - Object { - "name": , - "render": [Function], - }, - Object { - "actions": Array [ - Object { - "available": [Function], - "color": "danger", - "data-test-subj": "colorEditorRemoveColor", - "description": "Delete color format", - "icon": "trash", - "name": "Delete", - "onClick": [Function], - "type": "icon", - }, - ], - "field": "actions", - "name": "Actions", - }, - ] - } - items={ - Array [ + + + +

+ +

+
+ ", "text": "#000000", - }, - ] - } - noItemsMessage={ - - } - tableLayout="fixed" - /> + } + } + fieldType="string" + index={0} + key="0" + onColorChange={[Function]} + onRemoveColor={[Function]} + showDeleteButton={false} + /> +
diff --git a/src/platform/plugins/shared/data_view_field_editor/public/components/field_format_editor/editors/color/color.tsx b/src/platform/plugins/shared/data_view_field_editor/public/components/field_format_editor/editors/color/color.tsx index 85343826a58f3..5ecf50e7a6f74 100644 --- a/src/platform/plugins/shared/data_view_field_editor/public/components/field_format_editor/editors/color/color.tsx +++ b/src/platform/plugins/shared/data_view_field_editor/public/components/field_format_editor/editors/color/color.tsx @@ -7,38 +7,18 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import React, { Fragment } from 'react'; +import React from 'react'; -import { - EuiBasicTable, - EuiButton, - EuiColorPicker, - EuiIcon, - EuiFieldText, - EuiSelect, - EuiSpacer, -} from '@elastic/eui'; +import { EuiButton, EuiFlexGroup, EuiSpacer, EuiTitle } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { DEFAULT_CONVERTER_COLOR } from '@kbn/field-formats-plugin/common'; +import { Color, ColorRow } from './color_row'; import { DefaultFormatEditor } from '../default/default'; import { formatId } from './constants'; import { FormatEditorProps } from '../types'; -interface Color { - range?: string; - regex?: string; - boolean?: string; - text: string; - background: string; -} - -interface IndexedColor extends Color { - index: number; -} - export interface ColorFormatEditorFormatParams { colors: Color[]; } @@ -78,263 +58,44 @@ export class ColorFormatEditor extends DefaultFormatEditor { - if (fieldType === 'boolean') - return { - field: 'boolean', - name: ( - - ), - render: (value: string, item: IndexedColor) => { - return ( - { - this.onColorChange( - { - boolean: e.target.value, - }, - item.index - ); - }} - /> - ); - }, - }; - if (fieldType === 'string') - return { - field: 'regex', - name: ( - - ), - render: (value: string, item: IndexedColor) => { - return ( - { - this.onColorChange( - { - regex: e.target.value, - }, - item.index - ); - }} - /> - ); - }, - }; - return { - field: 'range', - name: ( - - ), - render: (value: string, item: IndexedColor) => { - return ( - { - this.onColorChange( - { - range: e.target.value, - }, - item.index - ); - }} - /> - ); - }, - }; - }; - render() { const { formatParams, fieldType } = this.props; - const items = - (formatParams.colors && - formatParams.colors.length && - formatParams.colors.map((color, index) => { - return { - ...color, - index, - }; - })) || - []; - - const columns = [ - this.getFirstColumn(fieldType), - { - field: 'text', - name: ( - - ), - render: (color: string, item: IndexedColor) => { - return ( - { - this.onColorChange( - { - text: newColor, - }, - item.index - ); - }} - button={ - {}} - aria-label={i18n.translate( - 'indexPatternFieldEditor.color.letteringButtonAriaLabel', - { - defaultMessage: 'Select a text color for item {index}', - values: { - index: item.index, - }, - } - )} - > - - - } - secondaryInputDisplay="bottom" - /> - ); - }, - }, - { - field: 'background', - name: ( - - ), - render: (color: string, item: IndexedColor) => { - return ( - { - this.onColorChange( - { - background: newColor, - }, - item.index - ); - }} - button={ - {}} - aria-label={i18n.translate( - 'indexPatternFieldEditor.color.letteringButtonAriaLabel', - { - defaultMessage: 'Select a background color for item {index}', - values: { - index: item.index, - }, - } - )} - > - - - } - secondaryInputDisplay="bottom" - /> - ); - }, - }, - { - name: ( - - ), - render: (item: IndexedColor) => { - return ( -
- 123456 -
- ); - }, - }, - { - field: 'actions', - name: i18n.translate('indexPatternFieldEditor.color.actions', { - defaultMessage: 'Actions', - }), - actions: [ - { - name: i18n.translate('indexPatternFieldEditor.color.deleteAria', { - defaultMessage: 'Delete', - }), - description: i18n.translate('indexPatternFieldEditor.color.deleteTitle', { - defaultMessage: 'Delete color format', - }), - onClick: (item: IndexedColor) => { - this.removeColor(item.index); - }, - type: 'icon', - icon: 'trash', - color: 'danger', - available: () => items.length > 1, - 'data-test-subj': 'colorEditorRemoveColor', - }, - ], - }, - ]; + const colors = formatParams?.colors; return ( - - + <> + + + +

+ +

+
+ {colors?.length > 0 && + colors.map((color, index) => { + return ( + 1} + /> + ); + })} +
-
+ ); } } diff --git a/src/platform/plugins/shared/data_view_field_editor/public/components/field_format_editor/editors/color/color_row.tsx b/src/platform/plugins/shared/data_view_field_editor/public/components/field_format_editor/editors/color/color_row.tsx new file mode 100644 index 0000000000000..2cf0260c05cdf --- /dev/null +++ b/src/platform/plugins/shared/data_view_field_editor/public/components/field_format_editor/editors/color/color_row.tsx @@ -0,0 +1,205 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import React from 'react'; + +import { + EuiButton, + EuiButtonIcon, + EuiColorPicker, + EuiFieldText, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiSelect, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +export interface Color { + range?: string; + regex?: string; + boolean?: string; + text: string; + background: string; +} + +interface ColorRowProps { + color: Color; + index: number; + fieldType: string; + showDeleteButton: boolean; + onColorChange: (newColorParams: Partial, index: number) => void; + onRemoveColor: (index: number) => void; +} + +export const ColorRow = ({ + color, + index, + fieldType, + showDeleteButton, + onColorChange, + onRemoveColor, +}: ColorRowProps) => { + const { range, regex, boolean, text, background } = color; + + const getInputByFieldType = () => { + if (fieldType === 'boolean') + return ( + { + onColorChange( + { + boolean: e.target.value, + }, + index + ); + }} + /> + ); + if (fieldType === 'string') + return ( + { + onColorChange( + { + regex: e.target.value, + }, + index + ); + }} + /> + ); + return ( + { + onColorChange( + { + range: e.target.value, + }, + index + ); + }} + /> + ); + }; + + return ( + + {getInputByFieldType()} + + { + onColorChange( + { + text: newColor, + }, + index + ); + }} + button={ + {}} + aria-label={i18n.translate('indexPatternFieldEditor.color.letteringButtonAriaLabel', { + defaultMessage: 'Select a text color for item {index}', + values: { + index, + }, + })} + > + + + } + secondaryInputDisplay="bottom" + /> + + + { + onColorChange( + { + background: newColor, + }, + index + ); + }} + button={ + {}} + aria-label={i18n.translate('indexPatternFieldEditor.color.letteringButtonAriaLabel', { + defaultMessage: 'Select a background color for item {index}', + values: { + index, + }, + })} + > + + + } + secondaryInputDisplay="bottom" + /> + + {showDeleteButton && ( + + { + onRemoveColor(index); + }} + aria-label={i18n.translate('indexPatternFieldEditor.color.deleteTitle', { + defaultMessage: 'Delete color format', + })} + data-test-subj="colorEditorRemoveColor" + /> + + )} + + ); +}; diff --git a/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_histogram_layout.tsx b/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_histogram_layout.tsx index 20afaf22373d5..65c92734eab92 100644 --- a/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_histogram_layout.tsx +++ b/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_histogram_layout.tsx @@ -7,16 +7,13 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import React, { useCallback, useMemo } from 'react'; +import React, { useCallback } from 'react'; import { UnifiedHistogramContainer } from '@kbn/unified-histogram-plugin/public'; import { css } from '@emotion/react'; import useObservable from 'react-use/lib/useObservable'; -import { ESQL_TABLE_TYPE } from '@kbn/data-plugin/common'; -import type { Datatable } from '@kbn/expressions-plugin/common'; import { useDiscoverHistogram } from './use_discover_histogram'; import { type DiscoverMainContentProps, DiscoverMainContent } from './discover_main_content'; import { useAppStateSelector } from '../../state_management/discover_app_state_container'; -import { FetchStatus } from '../../../types'; import { useIsEsqlMode } from '../../hooks/use_is_esql_mode'; export interface DiscoverHistogramLayoutProps extends DiscoverMainContentProps { @@ -44,7 +41,6 @@ export const DiscoverHistogramLayout = ({ hideChart, }); - const datatable = useObservable(dataState.data$.documents$); const renderCustomChartToggleActions = useCallback( () => React.isValidElement(panelsToggle) @@ -53,23 +49,6 @@ export const DiscoverHistogramLayout = ({ [panelsToggle] ); - const table: Datatable | undefined = useMemo(() => { - if ( - isEsqlMode && - datatable && - [FetchStatus.PARTIAL, FetchStatus.COMPLETE].includes(datatable.fetchStatus) - ) { - return { - type: 'datatable' as 'datatable', - rows: datatable.result!.map((r) => r.raw), - columns: datatable.esqlQueryColumns || [], - meta: { - type: ESQL_TABLE_TYPE, - }, - }; - } - }, [datatable, isEsqlMode]); - // Initialized when the first search has been requested or // when in ES|QL mode since search sessions are not supported if (!searchSessionId && !isEsqlMode) { @@ -81,7 +60,6 @@ export const DiscoverHistogramLayout = ({ {...unifiedHistogramProps} searchSessionId={searchSessionId} requestAdapter={dataState.inspectorAdapters.requests} - table={table} container={container} css={histogramLayoutCss} renderCustomChartToggleActions={renderCustomChartToggleActions} diff --git a/src/platform/plugins/shared/discover/public/application/main/components/layout/use_discover_histogram.test.tsx b/src/platform/plugins/shared/discover/public/application/main/components/layout/use_discover_histogram.test.tsx index 863a162c63a93..72f9af5c40fa1 100644 --- a/src/platform/plugins/shared/discover/public/application/main/components/layout/use_discover_histogram.test.tsx +++ b/src/platform/plugins/shared/discover/public/application/main/components/layout/use_discover_histogram.test.tsx @@ -161,7 +161,6 @@ describe('useDiscoverHistogram', () => { const { hook } = await renderUseDiscoverHistogram(); const params = hook.result.current.getCreationOptions(); expect(params?.localStorageKeyPrefix).toBe('discover'); - expect(params?.disableAutoFetching).toBe(true); expect(Object.keys(params?.initialState ?? {})).toEqual([ 'chartHidden', 'timeInterval', @@ -398,8 +397,8 @@ describe('useDiscoverHistogram', () => { }); }); - describe('refetching', () => { - it('should call refetch when savedSearchFetch$ is triggered', async () => { + describe('fetching', () => { + it('should call fetch when savedSearchFetch$ is triggered', async () => { const savedSearchFetch$ = new Subject(); const stateContainer = getStateContainer(); stateContainer.dataState.fetchChart$ = savedSearchFetch$; @@ -408,33 +407,11 @@ describe('useDiscoverHistogram', () => { act(() => { hook.result.current.ref(api); }); - expect(api.refetch).toHaveBeenCalled(); + expect(api.fetch).toHaveBeenCalled(); act(() => { savedSearchFetch$.next(); }); - expect(api.refetch).toHaveBeenCalledTimes(2); - }); - - it('should skip the next refetch when hideChart changes from true to false', async () => { - const savedSearchFetch$ = new Subject(); - const stateContainer = getStateContainer(); - stateContainer.dataState.fetchChart$ = savedSearchFetch$; - const { hook, initialProps } = await renderUseDiscoverHistogram({ stateContainer }); - const api = createMockUnifiedHistogramApi(); - act(() => { - hook.result.current.ref(api); - }); - expect(api.refetch).toHaveBeenCalled(); - act(() => { - hook.rerender({ ...initialProps, hideChart: true }); - }); - act(() => { - hook.rerender({ ...initialProps, hideChart: false }); - }); - act(() => { - savedSearchFetch$.next(); - }); - expect(api.refetch).toHaveBeenCalledTimes(1); + expect(api.fetch).toHaveBeenCalledTimes(2); }); }); diff --git a/src/platform/plugins/shared/discover/public/application/main/components/layout/use_discover_histogram.ts b/src/platform/plugins/shared/discover/public/application/main/components/layout/use_discover_histogram.ts index 8f0a0fdf33dc1..43b017337e25e 100644 --- a/src/platform/plugins/shared/discover/public/application/main/components/layout/use_discover_histogram.ts +++ b/src/platform/plugins/shared/discover/public/application/main/components/layout/use_discover_histogram.ts @@ -19,7 +19,7 @@ import { UnifiedHistogramVisContext, } from '@kbn/unified-histogram-plugin/public'; import { isEqual } from 'lodash'; -import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import { debounceTime, distinctUntilChanged, @@ -28,13 +28,15 @@ import { merge, Observable, pairwise, + skip, startWith, } from 'rxjs'; import useObservable from 'react-use/lib/useObservable'; import type { RequestAdapter } from '@kbn/inspector-plugin/common'; -import type { DatatableColumn } from '@kbn/expressions-plugin/common'; +import type { Datatable, DatatableColumn } from '@kbn/expressions-plugin/common'; import type { SavedSearch } from '@kbn/saved-search-plugin/common'; -import { Filter } from '@kbn/es-query'; +import { Filter, isOfAggregateQueryType } from '@kbn/es-query'; +import { ESQL_TABLE_TYPE } from '@kbn/data-plugin/common'; import { useDiscoverCustomization } from '../../../../customizations'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { FetchStatus } from '../../../types'; @@ -240,6 +242,7 @@ export const useDiscoverHistogram = ({ dataView: esqlDataView, query: esqlQuery, columns: esqlColumns, + table, } = useObservable(esqlFetchComplete$, initialEsqlProps); useEffect(() => { @@ -249,9 +252,7 @@ export const useDiscoverHistogram = ({ } const fetchStart = stateContainer.dataState.fetchChart$.subscribe(() => { - if (!skipRefetch.current) { - setIsSuggestionLoading(true); - } + setIsSuggestionLoading(true); }); const fetchComplete = esqlFetchComplete$.subscribe(() => { setIsSuggestionLoading(false); @@ -267,18 +268,6 @@ export const useDiscoverHistogram = ({ * Data fetching */ - const skipRefetch = useRef(); - - // Skip refetching when showing the chart since Lens will - // automatically fetch when the chart is shown - useEffect(() => { - if (skipRefetch.current === undefined) { - skipRefetch.current = false; - } else { - skipRefetch.current = !hideChart; - } - }, [hideChart]); - // Handle unified histogram refetching useEffect(() => { if (!unifiedHistogram) { @@ -304,18 +293,14 @@ export const useDiscoverHistogram = ({ } const subscription = fetchChart$.subscribe((source) => { - if (!skipRefetch.current) { - if (source === 'discover') addLog('Unified Histogram - Discover refetch'); - if (source === 'lens') addLog('Unified Histogram - Lens suggestion refetch'); - unifiedHistogram.refetch(); - } - - skipRefetch.current = false; + if (source === 'discover') addLog('Unified Histogram - Discover refetch'); + if (source === 'lens') addLog('Unified Histogram - Lens suggestion refetch'); + unifiedHistogram.fetch(); }); - // triggering the initial request for total hits hook - if (!isEsqlMode && !skipRefetch.current) { - unifiedHistogram.refetch(); + // triggering the initial chart request + if (!isEsqlMode) { + unifiedHistogram.fetch(); } return () => { @@ -397,6 +382,7 @@ export const useDiscoverHistogram = ({ timeRange: timeRangeMemoized, relativeTimeRange, columns: isEsqlMode ? esqlColumns : undefined, + table: isEsqlMode ? table : undefined, onFilter: histogramCustomization?.onFilter, onBrushEnd: histogramCustomization?.onBrushEnd, withDefaultActions: histogramCustomization?.withDefaultActions, @@ -495,7 +481,10 @@ const createTotalHitsObservable = (state$?: Observable) = const createCurrentSuggestionObservable = (state$: Observable) => { return state$.pipe( map((state) => state.currentSuggestionContext), - distinctUntilChanged(isEqual) + distinctUntilChanged(isEqual), + // Skip the first emission since it's the + // initial state and doesn't need a refetch + skip(1) ); }; @@ -507,11 +496,23 @@ function getUnifiedHistogramPropsForEsql({ savedSearch: SavedSearch; }) { const columns = documentsValue?.esqlQueryColumns || EMPTY_ESQL_COLUMNS; + const query = savedSearch.searchSource.getField('query'); + const isEsqlMode = isOfAggregateQueryType(query); + const table: Datatable | undefined = + isEsqlMode && documentsValue?.result + ? { + type: 'datatable', + rows: documentsValue.result.map((r) => r.raw), + columns, + meta: { type: ESQL_TABLE_TYPE }, + } + : undefined; const nextProps = { dataView: savedSearch.searchSource.getField('index')!, query: savedSearch.searchSource.getField('query'), columns, + table, }; addLog('[UnifiedHistogram] delayed next props for ES|QL', nextProps); diff --git a/src/platform/plugins/shared/discover/public/application/main/state_management/utils/build_state_subscribe.ts b/src/platform/plugins/shared/discover/public/application/main/state_management/utils/build_state_subscribe.ts index f809dd2fe3ff4..182ca600b111f 100644 --- a/src/platform/plugins/shared/discover/public/application/main/state_management/utils/build_state_subscribe.ts +++ b/src/platform/plugins/shared/discover/public/application/main/state_management/utils/build_state_subscribe.ts @@ -85,10 +85,9 @@ export const buildStateSubscribe = } } - const { hideChart, interval, breakdownField, sampleSize, sort, dataSource } = prevState; + const { interval, breakdownField, sampleSize, sort, dataSource } = prevState; // Cast to boolean to avoid false positives when comparing // undefined and false, which would trigger a refetch - const chartDisplayChanged = Boolean(nextState.hideChart) !== Boolean(hideChart); const chartIntervalChanged = nextState.interval !== interval && !isEsqlMode; const breakdownFieldChanged = nextState.breakdownField !== breakdownField; const sampleSizeChanged = nextState.sampleSize !== sampleSize; @@ -137,7 +136,6 @@ export const buildStateSubscribe = } if ( - chartDisplayChanged || chartIntervalChanged || breakdownFieldChanged || sampleSizeChanged || @@ -146,7 +144,6 @@ export const buildStateSubscribe = queryChanged ) { const logData = { - chartDisplayChanged: logEntry(chartDisplayChanged, hideChart, nextState.hideChart), chartIntervalChanged: logEntry(chartIntervalChanged, interval, nextState.interval), breakdownFieldChanged: logEntry( breakdownFieldChanged, diff --git a/src/platform/plugins/shared/discover/public/context_awareness/profile_providers/observability/logs_data_source_profile/profile.test.ts b/src/platform/plugins/shared/discover/public/context_awareness/profile_providers/observability/logs_data_source_profile/profile.test.ts index 7740602203e5a..1e84012942c16 100644 --- a/src/platform/plugins/shared/discover/public/context_awareness/profile_providers/observability/logs_data_source_profile/profile.test.ts +++ b/src/platform/plugins/shared/discover/public/context_awareness/profile_providers/observability/logs_data_source_profile/profile.test.ts @@ -28,9 +28,20 @@ const mockServices = createContextAwarenessMocks().profileProviderServices; describe('logsDataSourceProfileProvider', () => { const logsDataSourceProfileProvider = createLogsDataSourceProfileProvider(mockServices); - const VALID_INDEX_PATTERN = 'logs-nginx.access-*'; - const MIXED_INDEX_PATTERN = 'logs-nginx.access-*,metrics-*'; - const INVALID_INDEX_PATTERN = 'my_source-access-*'; + + const VALID_IMPLICIT_DATA_INDEX_PATTERN = 'logs-nginx.access-*'; + const VALID_INDEX_PATTERNS: Array<[string, string]> = [ + ['explicit data', 'logs-nginx.access-*::data'], + ['implicit data', VALID_IMPLICIT_DATA_INDEX_PATTERN], + ['mixed data selector qualification', 'logs-nginx.access-*::data,logs-nginx.error-*'], + ]; + const INVALID_INDEX_PATTERNS: Array<[string, string]> = [ + ['forbidden implicit data', 'my_source-access-*'], + ['mixed implicit data', 'logs-nginx.access-*,metrics-*'], + ['mixed explicit data', 'logs-nginx.access-*::data,metrics-*::data'], + ['mixed selector', 'logs-nginx.access-*,logs-nginx.access-*::failures'], + ]; + const ROOT_CONTEXT: ContextWithProfileId = { profileId: OBSERVABILITY_ROOT_PROFILE_ID, solutionType: SolutionType.Observability, @@ -43,64 +54,62 @@ describe('logsDataSourceProfileProvider', () => { isMatch: false, }; - it('should match ES|QL sources with an allowed index pattern in its query', () => { - expect( - logsDataSourceProfileProvider.resolve({ - rootContext: ROOT_CONTEXT, - dataSource: createEsqlDataSource(), - query: { esql: `from ${VALID_INDEX_PATTERN}` }, - }) - ).toEqual(RESOLUTION_MATCH); - }); - - it('should NOT match ES|QL sources with a mixed or not allowed index pattern in its query', () => { - expect( - logsDataSourceProfileProvider.resolve({ - rootContext: ROOT_CONTEXT, - dataSource: createEsqlDataSource(), - query: { esql: `from ${INVALID_INDEX_PATTERN}` }, - }) - ).toEqual(RESOLUTION_MISMATCH); - expect( - logsDataSourceProfileProvider.resolve({ - rootContext: ROOT_CONTEXT, - dataSource: createEsqlDataSource(), - query: { esql: `from ${MIXED_INDEX_PATTERN}` }, - }) - ).toEqual(RESOLUTION_MISMATCH); - }); - - it('should match data view sources with an allowed index pattern', () => { - expect( - logsDataSourceProfileProvider.resolve({ - rootContext: ROOT_CONTEXT, - dataSource: createDataViewDataSource({ dataViewId: VALID_INDEX_PATTERN }), - dataView: createStubIndexPattern({ spec: { title: VALID_INDEX_PATTERN } }), - }) - ).toEqual(RESOLUTION_MATCH); - }); - - it('should NOT match data view sources with a mixed or not allowed index pattern', () => { - expect( - logsDataSourceProfileProvider.resolve({ - rootContext: ROOT_CONTEXT, - dataSource: createDataViewDataSource({ dataViewId: INVALID_INDEX_PATTERN }), - dataView: createStubIndexPattern({ spec: { title: INVALID_INDEX_PATTERN } }), - }) - ).toEqual(RESOLUTION_MISMATCH); - expect( - logsDataSourceProfileProvider.resolve({ - rootContext: ROOT_CONTEXT, - dataSource: createDataViewDataSource({ dataViewId: MIXED_INDEX_PATTERN }), - dataView: createStubIndexPattern({ spec: { title: MIXED_INDEX_PATTERN } }), - }) - ).toEqual(RESOLUTION_MISMATCH); - }); + it.each(VALID_INDEX_PATTERNS)( + 'should match ES|QL sources with an allowed %s index pattern in its query', + (_, validIndexPattern) => { + expect( + logsDataSourceProfileProvider.resolve({ + rootContext: ROOT_CONTEXT, + dataSource: createEsqlDataSource(), + query: { esql: `from ${validIndexPattern}` }, + }) + ).toEqual(RESOLUTION_MATCH); + } + ); + + it.each(INVALID_INDEX_PATTERNS)( + 'should NOT match ES|QL sources with a %s index pattern in its query', + (_, invalidIndexPattern) => { + expect( + logsDataSourceProfileProvider.resolve({ + rootContext: ROOT_CONTEXT, + dataSource: createEsqlDataSource(), + query: { esql: `from ${invalidIndexPattern}` }, + }) + ).toEqual(RESOLUTION_MISMATCH); + } + ); + + it.each(VALID_INDEX_PATTERNS)( + 'should match data view sources with an allowed %s index pattern', + (_, validIndexPattern) => { + expect( + logsDataSourceProfileProvider.resolve({ + rootContext: ROOT_CONTEXT, + dataSource: createDataViewDataSource({ dataViewId: validIndexPattern }), + dataView: createStubIndexPattern({ spec: { title: validIndexPattern } }), + }) + ).toEqual(RESOLUTION_MATCH); + } + ); + + it.each(INVALID_INDEX_PATTERNS)( + 'should NOT match data view sources with a %s index pattern', + (_, invalidIndexPattern) => { + expect( + logsDataSourceProfileProvider.resolve({ + rootContext: ROOT_CONTEXT, + dataSource: createDataViewDataSource({ dataViewId: invalidIndexPattern }), + dataView: createStubIndexPattern({ spec: { title: invalidIndexPattern } }), + }) + ).toEqual(RESOLUTION_MISMATCH); + } + ); it('does NOT match data view sources when solution type is not Observability', () => { const params: Omit = { dataSource: createEsqlDataSource(), - query: { esql: `from ${VALID_INDEX_PATTERN}` }, + query: { esql: `from ${VALID_IMPLICIT_DATA_INDEX_PATTERN}` }, }; expect(logsDataSourceProfileProvider.resolve({ ...params, rootContext: ROOT_CONTEXT })).toEqual( RESOLUTION_MATCH @@ -127,7 +136,7 @@ describe('logsDataSourceProfileProvider', () => { const dataViewWithLogLevel = createStubIndexPattern({ spec: { - title: VALID_INDEX_PATTERN, + title: VALID_IMPLICIT_DATA_INDEX_PATTERN, fields: { 'log.level': { name: 'log.level', @@ -146,7 +155,7 @@ describe('logsDataSourceProfileProvider', () => { const dataViewWithoutLogLevel = createStubIndexPattern({ spec: { - title: VALID_INDEX_PATTERN, + title: VALID_IMPLICIT_DATA_INDEX_PATTERN, }, }); diff --git a/src/platform/plugins/shared/discover/public/context_awareness/profile_providers/observability/logs_data_source_profile/sub_profiles/create_resolve.ts b/src/platform/plugins/shared/discover/public/context_awareness/profile_providers/observability/logs_data_source_profile/sub_profiles/create_resolve.ts index fb2afd46066ca..822d8c5e065eb 100644 --- a/src/platform/plugins/shared/discover/public/context_awareness/profile_providers/observability/logs_data_source_profile/sub_profiles/create_resolve.ts +++ b/src/platform/plugins/shared/discover/public/context_awareness/profile_providers/observability/logs_data_source_profile/sub_profiles/create_resolve.ts @@ -14,7 +14,7 @@ import { OBSERVABILITY_ROOT_PROFILE_ID } from '../../consts'; export const createResolve = (baseIndexPattern: string): DataSourceProfileProvider['resolve'] => { const testIndexPattern = testPatternAgainstAllowedList([ - createRegExpPatternFrom(baseIndexPattern), + createRegExpPatternFrom(baseIndexPattern, 'data'), ]); return (params) => { diff --git a/src/platform/plugins/shared/discover/public/embeddable/get_search_embeddable_factory.tsx b/src/platform/plugins/shared/discover/public/embeddable/get_search_embeddable_factory.tsx index 298ac7bc20b9e..7766765a75e52 100644 --- a/src/platform/plugins/shared/discover/public/embeddable/get_search_embeddable_factory.tsx +++ b/src/platform/plugins/shared/discover/public/embeddable/get_search_embeddable_factory.tsx @@ -7,7 +7,6 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { omit } from 'lodash'; import React, { useCallback, useEffect, useMemo } from 'react'; import { BehaviorSubject, firstValueFrom } from 'rxjs'; @@ -120,6 +119,16 @@ export const getSearchEmbeddableFactory = ({ stateManager: searchEmbeddable.stateManager, }); + const serialize = (savedObjectId?: string) => + serializeState({ + uuid, + initialState, + savedSearch: searchEmbeddable.api.savedSearch$.getValue(), + serializeTitles, + serializeTimeRange: timeRange.serialize, + savedObjectId, + }); + const api: SearchEmbeddableApi = buildApi( { ...titlesApi, @@ -137,15 +146,6 @@ export const getSearchEmbeddableFactory = ({ savedObjectId: savedObjectId$, defaultPanelTitle: defaultPanelTitle$, defaultPanelDescription: defaultPanelDescription$, - getByValueRuntimeSnapshot: () => { - const savedSearch = searchEmbeddable.api.savedSearch$.getValue(); - return { - ...serializeTitles(), - ...timeRange.serialize(), - ...omit(savedSearch, 'searchSource'), - serializedSearchSource: savedSearch.searchSource.getSerializedFields(), - }; - }, hasTimeRange: () => { const fetchContext = fetchContext$.getValue(); return fetchContext?.timeslice !== undefined || fetchContext?.timeRange !== undefined; @@ -160,14 +160,12 @@ export const getSearchEmbeddableFactory = ({ ); }, canUnlinkFromLibrary: async () => Boolean(savedObjectId$.getValue()), - libraryId$: savedObjectId$, saveToLibrary: async (title: string) => { const savedObjectId = await save({ ...api.savedSearch$.getValue(), title, }); defaultPanelTitle$.next(title); - savedObjectId$.next(savedObjectId!); return savedObjectId!; }, checkForDuplicateTitle: (newTitle, isTitleDuplicateConfirmed, onTitleDuplicate) => @@ -176,26 +174,9 @@ export const getSearchEmbeddableFactory = ({ isTitleDuplicateConfirmed, onTitleDuplicate, }), - unlinkFromLibrary: () => { - savedObjectId$.next(undefined); - if ((titlesApi.panelTitle.getValue() ?? '').length === 0) { - titlesApi.setPanelTitle(defaultPanelTitle$.getValue()); - } - if ((titlesApi.panelDescription.getValue() ?? '').length === 0) { - titlesApi.setPanelDescription(defaultPanelDescription$.getValue()); - } - defaultPanelTitle$.next(undefined); - defaultPanelDescription$.next(undefined); - }, - serializeState: () => - serializeState({ - uuid, - initialState, - savedSearch: searchEmbeddable.api.savedSearch$.getValue(), - serializeTitles, - serializeTimeRange: timeRange.serialize, - savedObjectId: savedObjectId$.getValue(), - }), + getSerializedStateByValue: () => serialize(undefined), + getSerializedStateByReference: (newId: string) => serialize(newId), + serializeState: () => serialize(savedObjectId$.getValue()), getInspectorAdapters: () => searchEmbeddable.stateManager.inspectorAdapters.getValue(), }, { diff --git a/src/platform/plugins/shared/discover/public/embeddable/types.ts b/src/platform/plugins/shared/discover/public/embeddable/types.ts index 57932b2508ee1..05c1991bce611 100644 --- a/src/platform/plugins/shared/discover/public/embeddable/types.ts +++ b/src/platform/plugins/shared/discover/public/embeddable/types.ts @@ -13,7 +13,7 @@ import { HasInspectorAdapters } from '@kbn/inspector-plugin/public'; import { EmbeddableApiContext, HasEditCapabilities, - HasInPlaceLibraryTransforms, + HasLibraryTransforms, PublishesBlockingError, PublishesDataLoading, PublishesSavedObjectId, @@ -104,7 +104,7 @@ export type SearchEmbeddableApi = DefaultEmbeddableApi< PublishesSavedSearch & PublishesWritableDataViews & PublishesWritableUnifiedSearch & - HasInPlaceLibraryTransforms & + HasLibraryTransforms & HasTimeRange & HasInspectorAdapters & Partial; diff --git a/src/platform/plugins/shared/discover/public/embeddable/utils/serialization_utils.test.ts b/src/platform/plugins/shared/discover/public/embeddable/utils/serialization_utils.test.ts index 2a7a23b3600a7..a4ab454c8a49c 100644 --- a/src/platform/plugins/shared/discover/public/embeddable/utils/serialization_utils.test.ts +++ b/src/platform/plugins/shared/discover/public/embeddable/utils/serialization_utils.test.ts @@ -10,7 +10,7 @@ import { SerializedSearchSourceFields } from '@kbn/data-plugin/common'; import { createSearchSourceMock } from '@kbn/data-plugin/public/mocks'; import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; -import { SerializedPanelState } from '@kbn/presentation-containers'; +import { SerializedPanelState } from '@kbn/presentation-publishing'; import { toSavedSearchAttributes } from '@kbn/saved-search-plugin/common'; import { SavedSearchUnwrapResult } from '@kbn/saved-search-plugin/public'; import { discoverServiceMock } from '../../__mocks__/services'; diff --git a/src/platform/plugins/shared/discover/public/embeddable/utils/serialization_utils.ts b/src/platform/plugins/shared/discover/public/embeddable/utils/serialization_utils.ts index 397d078dba3e3..fb6eeed18f85f 100644 --- a/src/platform/plugins/shared/discover/public/embeddable/utils/serialization_utils.ts +++ b/src/platform/plugins/shared/discover/public/embeddable/utils/serialization_utils.ts @@ -11,8 +11,11 @@ import { omit, pick } from 'lodash'; import deepEqual from 'react-fast-compare'; import { EmbeddableStateWithType } from '@kbn/embeddable-plugin/common'; -import { SerializedPanelState } from '@kbn/presentation-containers'; -import { SerializedTimeRange, SerializedTitles } from '@kbn/presentation-publishing'; +import { + SerializedTimeRange, + SerializedTitles, + SerializedPanelState, +} from '@kbn/presentation-publishing'; import { SavedSearch, SavedSearchAttributes, diff --git a/src/platform/plugins/shared/embeddable/public/index.ts b/src/platform/plugins/shared/embeddable/public/index.ts index 88dafd108e5ea..31da8691af17e 100644 --- a/src/platform/plugins/shared/embeddable/public/index.ts +++ b/src/platform/plugins/shared/embeddable/public/index.ts @@ -25,10 +25,8 @@ export { isValueClickTriggerContext, MULTI_VALUE_CLICK_TRIGGER, panelBadgeTrigger, - panelHoverTrigger, panelNotificationTrigger, PANEL_BADGE_TRIGGER, - PANEL_HOVER_TRIGGER, PANEL_NOTIFICATION_TRIGGER, SELECT_RANGE_TRIGGER, VALUE_CLICK_TRIGGER, diff --git a/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_renderer.tsx b/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_renderer.tsx index 2119e6de03a8a..65cbbf29f8aba 100644 --- a/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_renderer.tsx +++ b/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_renderer.tsx @@ -11,12 +11,15 @@ import { apiHasRuntimeChildState, apiIsPresentationContainer, HasSerializedChildState, - HasSnapshottableState, initializeUnsavedChanges, - SerializedPanelState, } from '@kbn/presentation-containers'; import { PresentationPanel, PresentationPanelProps } from '@kbn/presentation-panel-plugin/public'; -import { ComparatorDefinition, StateComparators } from '@kbn/presentation-publishing'; +import { + ComparatorDefinition, + StateComparators, + HasSnapshottableState, + SerializedPanelState, +} from '@kbn/presentation-publishing'; import React, { useEffect, useImperativeHandle, useMemo, useRef } from 'react'; import { BehaviorSubject, combineLatest, debounceTime, map, skip, Subscription } from 'rxjs'; import { v4 as generateId } from 'uuid'; diff --git a/src/platform/plugins/shared/embeddable/public/react_embeddable_system/types.ts b/src/platform/plugins/shared/embeddable/public/react_embeddable_system/types.ts index 4ba8653310ff0..db0818a76b826 100644 --- a/src/platform/plugins/shared/embeddable/public/react_embeddable_system/types.ts +++ b/src/platform/plugins/shared/embeddable/public/react_embeddable_system/types.ts @@ -7,11 +7,6 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { - HasSerializableState, - HasSnapshottableState, - SerializedPanelState, -} from '@kbn/presentation-containers'; import { DefaultPresentationPanelApi } from '@kbn/presentation-panel-plugin/public/panel_component/types'; import { CanLockHoverActions, @@ -19,6 +14,9 @@ import { PublishesPhaseEvents, PublishesUnsavedChanges, StateComparators, + HasSerializableState, + HasSnapshottableState, + SerializedPanelState, } from '@kbn/presentation-publishing'; import { MaybePromise } from '@kbn/utility-types'; import React from 'react'; diff --git a/src/platform/plugins/shared/embeddable/public/ui_actions/register_triggers.ts b/src/platform/plugins/shared/embeddable/public/ui_actions/register_triggers.ts index 97d2cf0f58399..b51dd18f6ec0a 100644 --- a/src/platform/plugins/shared/embeddable/public/ui_actions/register_triggers.ts +++ b/src/platform/plugins/shared/embeddable/public/ui_actions/register_triggers.ts @@ -16,12 +16,10 @@ import { selectRangeTrigger, valueClickTrigger, cellValueTrigger, - panelHoverTrigger, } from './triggers'; export const registerTriggers = (uiActions: UiActionsSetup) => { uiActions.registerTrigger(contextMenuTrigger); - uiActions.registerTrigger(panelHoverTrigger); uiActions.registerTrigger(panelBadgeTrigger); uiActions.registerTrigger(panelNotificationTrigger); uiActions.registerTrigger(selectRangeTrigger); diff --git a/src/platform/plugins/shared/embeddable/public/ui_actions/triggers.ts b/src/platform/plugins/shared/embeddable/public/ui_actions/triggers.ts index cdebc6129afb6..2eb67397a07f4 100644 --- a/src/platform/plugins/shared/embeddable/public/ui_actions/triggers.ts +++ b/src/platform/plugins/shared/embeddable/public/ui_actions/triggers.ts @@ -75,17 +75,6 @@ export const contextMenuTrigger: Trigger = { }), }; -export const PANEL_HOVER_TRIGGER = 'PANEL_HOVER_TRIGGER'; -export const panelHoverTrigger: Trigger = { - id: PANEL_HOVER_TRIGGER, - title: i18n.translate('embeddableApi.panelHoverTrigger.title', { - defaultMessage: 'Panel hover', - }), - description: i18n.translate('embeddableApi.panelHoverTrigger.description', { - defaultMessage: "A new action will be added to the panel's hover menu", - }), -}; - export const PANEL_BADGE_TRIGGER = 'PANEL_BADGE_TRIGGER'; export const panelBadgeTrigger: Trigger = { id: PANEL_BADGE_TRIGGER, diff --git a/src/platform/plugins/shared/field_formats/common/constants/color_default.ts b/src/platform/plugins/shared/field_formats/common/constants/color_default.ts index 8133d4611d1f8..29ba2e7d53084 100644 --- a/src/platform/plugins/shared/field_formats/common/constants/color_default.ts +++ b/src/platform/plugins/shared/field_formats/common/constants/color_default.ts @@ -8,7 +8,7 @@ */ export const DEFAULT_CONVERTER_COLOR = { - range: `${Number.NEGATIVE_INFINITY}:${Number.POSITIVE_INFINITY}`, + range: `min:max`, regex: '', text: '#000000', background: '#ffffff', diff --git a/src/platform/plugins/shared/presentation_util/public/components/index.tsx b/src/platform/plugins/shared/presentation_util/public/components/index.tsx index 80b8b22cd1d68..4195ef39f90b4 100644 --- a/src/platform/plugins/shared/presentation_util/public/components/index.tsx +++ b/src/platform/plugins/shared/presentation_util/public/components/index.tsx @@ -61,8 +61,6 @@ export { DEFAULT_DASHBOARD_DRILLDOWN_OPTIONS, } from './dashboard_drilldown_options/types'; -export { FloatingActions } from './floating_actions/floating_actions'; - /** * A lazily-loaded ExpressionInput component. */ diff --git a/src/platform/plugins/shared/presentation_util/public/components/types.ts b/src/platform/plugins/shared/presentation_util/public/components/types.ts index f7a479a58b2ef..64574bd7d0e82 100644 --- a/src/platform/plugins/shared/presentation_util/public/components/types.ts +++ b/src/platform/plugins/shared/presentation_util/public/components/types.ts @@ -13,7 +13,7 @@ import type { CSSProperties, HTMLAttributes } from 'react'; import type { ExpressionFunction } from '@kbn/expressions-plugin/common'; -import { OnSaveProps, SaveModalState } from '@kbn/saved-objects-plugin/public'; +import type { OnSaveProps, SaveModalState } from '@kbn/saved-objects-plugin/public'; interface SaveModalDocumentInfo { id?: string; diff --git a/src/platform/plugins/shared/presentation_util/public/index.ts b/src/platform/plugins/shared/presentation_util/public/index.ts index 76e7362c855ed..67790ec49f02a 100644 --- a/src/platform/plugins/shared/presentation_util/public/index.ts +++ b/src/platform/plugins/shared/presentation_util/public/index.ts @@ -24,7 +24,6 @@ export { withSuspense, LazyDataViewPicker, LazyFieldPicker, - FloatingActions, type DashboardDrilldownOptions, DashboardDrilldownOptionsComponent, DEFAULT_DASHBOARD_DRILLDOWN_OPTIONS, diff --git a/src/platform/plugins/shared/presentation_util/tsconfig.json b/src/platform/plugins/shared/presentation_util/tsconfig.json index 44f61e43b1c24..2be8e5c7ad207 100644 --- a/src/platform/plugins/shared/presentation_util/tsconfig.json +++ b/src/platform/plugins/shared/presentation_util/tsconfig.json @@ -15,7 +15,6 @@ "kbn_references": [ "@kbn/core", "@kbn/saved-objects-plugin", - "@kbn/embeddable-plugin", "@kbn/kibana-react-plugin", "@kbn/i18n", "@kbn/expressions-plugin", @@ -34,9 +33,7 @@ "@kbn/code-editor", "@kbn/calculate-width-from-char-count", "@kbn/field-utils", - "@kbn/presentation-publishing", "@kbn/core-ui-settings-browser", - "@kbn/presentation-panel-plugin", ], "exclude": ["target/**/*"] } diff --git a/src/platform/plugins/shared/telemetry/server/mocks.ts b/src/platform/plugins/shared/telemetry/server/mocks.ts index 79d583dde5559..fe22e45a343c2 100644 --- a/src/platform/plugins/shared/telemetry/server/mocks.ts +++ b/src/platform/plugins/shared/telemetry/server/mocks.ts @@ -8,6 +8,7 @@ */ import { URL } from 'url'; +import { Observable } from 'rxjs'; import { TelemetryPluginStart, TelemetryPluginSetup } from './plugin'; export type Setup = jest.Mocked; @@ -30,6 +31,7 @@ function createSetupContract(): Setup { function createStartContract(): Start { const startContract: Start = { getIsOptedIn: jest.fn(), + isOptedIn$: new Observable(), }; return startContract; diff --git a/src/platform/plugins/shared/telemetry/server/plugin.test.ts b/src/platform/plugins/shared/telemetry/server/plugin.test.ts index 131711076595b..389e7789770c3 100644 --- a/src/platform/plugins/shared/telemetry/server/plugin.test.ts +++ b/src/platform/plugins/shared/telemetry/server/plugin.test.ts @@ -15,6 +15,7 @@ import { telemetryCollectionManagerPluginMock } from '@kbn/telemetry-collection- import { buildShipperHeaders } from '../common/ebt_v3_endpoint'; import { TelemetryPlugin } from './plugin'; import type { NodeRoles } from '@kbn/core-node-server'; +import { Observable } from 'rxjs'; describe('TelemetryPlugin', () => { describe('setup', () => { @@ -108,11 +109,11 @@ describe('TelemetryPlugin', () => { telemetryCollectionManager: telemetryCollectionManagerPluginMock.createSetupContract(), }); - plugin.start(coreMock.createStart(), { + const returnedStartDependencies = plugin.start(coreMock.createStart(), { telemetryCollectionManager: telemetryCollectionManagerPluginMock.createStartContract(), }); - return { startFetcherMock }; + return { startFetcherMock, returnedStartDependencies }; } afterEach(() => { @@ -128,6 +129,12 @@ describe('TelemetryPlugin', () => { const { startFetcherMock } = createPluginForNodeRole({ ui: false }); expect(startFetcherMock).toHaveBeenCalledTimes(0); }); + + it('exposes isOptedIn$ Observable', () => { + const { returnedStartDependencies } = createPluginForNodeRole({ ui: true }); + expect(returnedStartDependencies).toHaveProperty('isOptedIn$'); + expect(returnedStartDependencies.isOptedIn$).toBeInstanceOf(Observable); + }); }); }); }); diff --git a/src/platform/plugins/shared/telemetry/server/plugin.ts b/src/platform/plugins/shared/telemetry/server/plugin.ts index bc18ba4e3fd21..a96d2fa01deb8 100644 --- a/src/platform/plugins/shared/telemetry/server/plugin.ts +++ b/src/platform/plugins/shared/telemetry/server/plugin.ts @@ -92,9 +92,23 @@ export interface TelemetryPluginStart { * Resolves `false` if the user explicitly opted out of sending usage data to Elastic * or did not choose to opt-in or out -yet- after a minor or major upgrade (only when previously opted-out). * - * @track-adoption + * @deprecated Use {@link TelemetryPluginStart.isOptedIn$ | isOptedIn$} instead. */ getIsOptedIn: () => Promise; + + /** + * An Observable object that can be subscribed to for changes in global telemetry config. + * + * Pushes `true` when sending usage to Elastic is enabled. + * Pushes `false` when the user explicitly opts out of sending usage data to Elastic. + * + * Additionally, pushes the actual value on Kibana startup, except if the (previously opted-out) user + * haven't chosen yet to opt-in or out after a minor or major upgrade. In that case, pushing the new + * value waits until the user decides. + * + * @track-adoption + */ + isOptedIn$: Observable; } export class TelemetryPlugin implements Plugin { @@ -270,6 +284,7 @@ export class TelemetryPlugin implements Plugin this.isOptedIn === true, + isOptedIn$: this.isOptedIn$, }; } diff --git a/src/platform/plugins/shared/unified_histogram/README.md b/src/platform/plugins/shared/unified_histogram/README.md index 4509f28a7a61e..177cd6524d0fa 100755 --- a/src/platform/plugins/shared/unified_histogram/README.md +++ b/src/platform/plugins/shared/unified_histogram/README.md @@ -7,30 +7,15 @@ It manages its own state and data fetching, and can easily be dropped into pages ```tsx // Import the container component -import { - UnifiedHistogramContainer, -} from '@kbn/unified-histogram-plugin/public'; +import { UnifiedHistogramContainer } from '@kbn/unified-histogram-plugin/public'; // Import modules required for your application -import { - useServices, - useResizeRef, - useRequestParams, - MyLayout, - MyButton, -} from './my-modules'; +import { useServices, useResizeRef, useRequestParams, MyLayout, MyButton } from './my-modules'; const services = useServices(); const resizeRef = useResizeRef(); -const { - dataView, - query, - filters, - timeRange, - relativeTimeRange, - searchSessionId, - requestAdapter, -} = useRequestParams(); +const { dataView, query, filters, timeRange, relativeTimeRange, searchSessionId, requestAdapter } = + useRequestParams(); return ( ({ // Optionally provide a local storage key prefix to save parts of the state, // such as the chart hidden state and top panel height, to local storage localStorageKeyPrefix: 'myApp', - // By default Unified Histogram will automatically refetch based on certain - // state changes, such as chart hidden and request params, but this can be - // disabled in favour of manual fetching if preferred. Note that an initial - // request is always triggered when first initialized, and when the chart - // changes from hidden to visible, Lens will automatically trigger a refetch - // regardless of what this property is set to - disableAutoFetching: true, // Customize the initial state in order to override the defaults initialState: { chartHidden, breakdownField }, }), [...]); -// Manually refetch if disableAutoFetching is true -useManualRefetch(() => { - unifiedHistogram?.refetch(); +// Trigger a fetch, must be called on init to render the chart +useFetch(() => { + unifiedHistogram?.fetch(); }); // Update the Unified Histogram state when our state params change diff --git a/src/platform/plugins/shared/unified_histogram/public/chart/chart.test.tsx b/src/platform/plugins/shared/unified_histogram/public/chart/chart.test.tsx index e127e1a4ab41c..abd72dd502cfe 100644 --- a/src/platform/plugins/shared/unified_histogram/public/chart/chart.test.tsx +++ b/src/platform/plugins/shared/unified_histogram/public/chart/chart.test.tsx @@ -19,7 +19,7 @@ import type { ReactWrapper } from 'enzyme'; import { unifiedHistogramServicesMock } from '../__mocks__/services'; import { getLensVisMock } from '../__mocks__/lens_vis'; import { searchSourceInstanceMock } from '@kbn/data-plugin/common/search/search_source/mocks'; -import { of } from 'rxjs'; +import { Subject, of } from 'rxjs'; import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; import { dataViewMock } from '../__mocks__/data_view'; import { BreakdownFieldSelector } from './breakdown_field_selector'; @@ -135,6 +135,7 @@ async function mountComponent({ withDefaultActions: undefined, isChartAvailable: checkChartAvailability({ chart, dataView, isPlainRecord }), renderCustomChartToggleActions: customToggle ? () => customToggle : undefined, + input$: new Subject(), }; let instance: ReactWrapper = {} as ReactWrapper; @@ -142,6 +143,7 @@ async function mountComponent({ instance = mountWithIntl(); // wait for initial async loading to complete await new Promise((r) => setTimeout(r, 0)); + props.input$?.next({ type: 'fetch' }); instance.update(); }); return instance; diff --git a/src/platform/plugins/shared/unified_histogram/public/chart/chart.tsx b/src/platform/plugins/shared/unified_histogram/public/chart/chart.tsx index 164d1eb539e3c..0b3ee3a0d7395 100644 --- a/src/platform/plugins/shared/unified_histogram/public/chart/chart.tsx +++ b/src/platform/plugins/shared/unified_histogram/public/chart/chart.tsx @@ -18,11 +18,19 @@ import type { LensEmbeddableInput, LensEmbeddableOutput, } from '@kbn/lens-plugin/public'; -import type { DatatableColumn } from '@kbn/expressions-plugin/common'; +import type { + Datatable, + DatatableColumn, + DefaultInspectorAdapters, +} from '@kbn/expressions-plugin/common'; import type { DataView, DataViewField } from '@kbn/data-views-plugin/public'; import type { TimeRange } from '@kbn/es-query'; +import { PublishingSubject } from '@kbn/presentation-publishing'; +import { RequestStatus } from '@kbn/inspector-plugin/public'; +import { IKibanaSearchResponse } from '@kbn/search-types'; +import { estypes } from '@elastic/elasticsearch'; import { Histogram } from './histogram'; -import type { +import { UnifiedHistogramSuggestionContext, UnifiedHistogramBreakdownContext, UnifiedHistogramChartContext, @@ -33,6 +41,7 @@ import type { UnifiedHistogramInputMessage, UnifiedHistogramRequestContext, UnifiedHistogramServices, + UnifiedHistogramBucketInterval, } from '../types'; import { UnifiedHistogramSuggestionType } from '../types'; import { BreakdownFieldSelector } from './breakdown_field_selector'; @@ -41,11 +50,14 @@ import { useTotalHits } from './hooks/use_total_hits'; import { useChartStyles } from './hooks/use_chart_styles'; import { useChartActions } from './hooks/use_chart_actions'; import { ChartConfigPanel } from './chart_config_panel'; -import { useRefetch } from './hooks/use_refetch'; +import { useFetch } from './hooks/use_fetch'; import { useEditVisualization } from './hooks/use_edit_visualization'; import { LensVisService } from '../services/lens_vis_service'; import type { UseRequestParamsResult } from '../hooks/use_request_params'; import { removeTablesFromLensAttributes } from '../utils/lens_vis_from_table'; +import { useLensProps } from './hooks/use_lens_props'; +import { useStableCallback } from '../hooks/use_stable_callback'; +import { buildBucketInterval } from './utils/build_bucket_interval'; export interface ChartProps { abortController?: AbortController; @@ -64,7 +76,6 @@ export interface ChartProps { breakdown?: UnifiedHistogramBreakdownContext; renderCustomChartToggleActions?: () => ReactElement | undefined; appendHistogram?: ReactElement; - disableAutoFetching?: boolean; disableTriggers?: LensEmbeddableInput['disableTriggers']; disabledActions?: LensEmbeddableInput['disabledActions']; input$?: UnifiedHistogramInput$; @@ -99,7 +110,6 @@ export function Chart({ isPlainRecord, renderCustomChartToggleActions, appendHistogram, - disableAutoFetching, disableTriggers, disabledActions, input$: originalInput$, @@ -140,20 +150,9 @@ export function Chart({ const { filters, query, getTimeRange, updateTimeRange, relativeTimeRange } = requestParams; - const refetch$ = useRefetch({ - dataView, - request, - hits, - chart, - chartVisible, - breakdown, - filters, - query, - relativeTimeRange, - currentSuggestion, - disableAutoFetching, + const fetch$ = useFetch({ input$, - beforeRefetch: updateTimeRange, + beforeFetch: updateTimeRange, }); useTotalHits({ @@ -165,11 +164,67 @@ export function Chart({ filters, query, getTimeRange, - refetch$, + fetch$, onTotalHitsChange, isPlainRecord, }); + const [bucketInterval, setBucketInterval] = useState(); + const onLoad = useStableCallback( + ( + isLoading: boolean, + adapters: Partial | undefined, + dataLoadingSubject$?: PublishingSubject + ) => { + const lensRequest = adapters?.requests?.getRequests()[0]; + const requestFailed = lensRequest?.status === RequestStatus.ERROR; + const json = lensRequest?.response?.json as + | IKibanaSearchResponse + | undefined; + const response = json?.rawResponse; + + if (requestFailed) { + onTotalHitsChange?.(UnifiedHistogramFetchStatus.error, undefined); + onChartLoad?.({ adapters: adapters ?? {} }); + return; + } + + const adapterTables = adapters?.tables?.tables; + const totalHits = computeTotalHits(hasLensSuggestions, adapterTables, isPlainRecord); + + if (response?._shards?.failed || response?.timed_out) { + onTotalHitsChange?.(UnifiedHistogramFetchStatus.error, totalHits); + } else { + onTotalHitsChange?.( + isLoading ? UnifiedHistogramFetchStatus.loading : UnifiedHistogramFetchStatus.complete, + totalHits ?? hits?.total + ); + } + + if (response) { + const newBucketInterval = buildBucketInterval({ + data: services.data, + dataView, + timeInterval: chart?.timeInterval, + timeRange: getTimeRange(), + response, + }); + + setBucketInterval(newBucketInterval); + } + + onChartLoad?.({ adapters: adapters ?? {}, dataLoading$: dataLoadingSubject$ }); + } + ); + + const lensPropsContext = useLensProps({ + request, + getTimeRange, + fetch$, + visContext, + onLoad, + }); + const { chartToolbarCss, histogramCss } = useChartStyles(chartVisible); const onSuggestionContextEdit = useCallback( @@ -356,26 +411,24 @@ export function Chart({ )} - + {lensPropsContext && ( + + )} {appendHistogram} @@ -405,3 +458,30 @@ export function Chart({ ); } + +const computeTotalHits = ( + hasLensSuggestions: boolean, + adapterTables: + | { + [key: string]: Datatable; + } + | undefined, + isPlainRecord?: boolean +) => { + if (isPlainRecord && hasLensSuggestions) { + return Object.values(adapterTables ?? {})?.[0]?.rows?.length; + } else if (isPlainRecord && !hasLensSuggestions) { + // ES|QL histogram case + const rows = Object.values(adapterTables ?? {})?.[0]?.rows; + if (!rows) { + return undefined; + } + let rowsCount = 0; + rows.forEach((r) => { + rowsCount += r.results; + }); + return rowsCount; + } else { + return adapterTables?.unifiedHistogram?.meta?.statistics?.totalCount; + } +}; diff --git a/src/platform/plugins/shared/unified_histogram/public/chart/histogram.test.tsx b/src/platform/plugins/shared/unified_histogram/public/chart/histogram.test.tsx index 7bef5d4f85554..be213b08a1ac9 100644 --- a/src/platform/plugins/shared/unified_histogram/public/chart/histogram.test.tsx +++ b/src/platform/plugins/shared/unified_histogram/public/chart/histogram.test.tsx @@ -8,23 +8,17 @@ */ import { mountWithIntl } from '@kbn/test-jest-helpers'; -import { Histogram } from './histogram'; +import { Histogram, HistogramProps } from './histogram'; import React from 'react'; import { BehaviorSubject, Subject } from 'rxjs'; import { unifiedHistogramServicesMock } from '../__mocks__/services'; import { getLensVisMock } from '../__mocks__/lens_vis'; import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; import { createDefaultInspectorAdapters } from '@kbn/expressions-plugin/common'; -import { UnifiedHistogramFetchStatus, UnifiedHistogramInput$ } from '../types'; +import { UnifiedHistogramInput$ } from '../types'; import { act } from 'react-dom/test-utils'; -import * as buildBucketInterval from './utils/build_bucket_interval'; -import * as useTimeRange from './hooks/use_time_range'; import { RequestStatus } from '@kbn/inspector-plugin/public'; -import { getLensProps } from './hooks/use_lens_props'; - -const mockBucketInterval = { description: '1 minute', scale: undefined, scaled: false }; -jest.spyOn(buildBucketInterval, 'buildBucketInterval').mockReturnValue(mockBucketInterval); -jest.spyOn(useTimeRange, 'useTimeRange'); +import { getLensProps, useLensProps } from './hooks/use_lens_props'; const getMockLensAttributes = async () => { const query = { @@ -44,46 +38,48 @@ const getMockLensAttributes = async () => { ).visContext; }; +type CombinedProps = Omit & + Parameters[0]; + async function mountComponent(isPlainRecord = false, hasLensSuggestions = false) { const services = unifiedHistogramServicesMock; services.data.query.timefilter.timefilter.getAbsoluteTime = () => { return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; }; - const timefilterUpdateHandler = jest.fn(); - const refetch$: UnifiedHistogramInput$ = new Subject(); - const props = { + const fetch$: UnifiedHistogramInput$ = new Subject(); + const props: CombinedProps = { services: unifiedHistogramServicesMock, request: { searchSessionId: '123', }, - hasLensSuggestions, isPlainRecord, - hits: { - status: UnifiedHistogramFetchStatus.loading, - total: undefined, - }, chart: { hidden: false, timeInterval: 'auto', }, - timefilterUpdateHandler, dataView: dataViewWithTimefieldMock, getTimeRange: () => ({ from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590', }), - refetch$, + fetch$, visContext: (await getMockLensAttributes())!, - onTotalHitsChange: jest.fn(), - onChartLoad: jest.fn(), + onLoad: jest.fn(), withDefaultActions: undefined, }; - - return { - props, - component: mountWithIntl(), + const Wrapper = (wrapperProps: CombinedProps) => { + const lensPropsContext = useLensProps(wrapperProps); + return lensPropsContext ? : null; }; + + const component = mountWithIntl(); + + act(() => { + fetch$?.next({ type: 'fetch' }); + }); + + return { props, fetch$, component: component.update() }; } describe('Histogram', () => { @@ -92,13 +88,13 @@ describe('Histogram', () => { expect(component.find('[data-test-subj="unifiedHistogramChart"]').exists()).toBe(true); }); - it('should only update lens.EmbeddableComponent props when refetch$ is triggered', async () => { - const { component, props } = await mountComponent(); + it('should only update lens.EmbeddableComponent props when fetch$ is triggered', async () => { + const { component, props, fetch$ } = await mountComponent(); const embeddable = unifiedHistogramServicesMock.lens.EmbeddableComponent; expect(component.find(embeddable).exists()).toBe(true); let lensProps = component.find(embeddable).props(); const originalProps = getLensProps({ - searchSessionId: props.request.searchSessionId, + searchSessionId: props.request?.searchSessionId, getTimeRange: props.getTimeRange, attributes: (await getMockLensAttributes())!.attributes, onLoad: lensProps.onLoad!, @@ -108,7 +104,7 @@ describe('Histogram', () => { lensProps = component.find(embeddable).props(); expect(lensProps).toMatchObject(expect.objectContaining(originalProps)); await act(async () => { - props.refetch$.next({ type: 'refetch' }); + fetch$.next({ type: 'fetch' }); }); component.update(); lensProps = component.find(embeddable).props(); @@ -174,27 +170,11 @@ describe('Histogram', () => { .mockReturnValue([{ response: { json: { rawResponse } } } as any]); const dataLoading$ = new BehaviorSubject(false); onLoad(true, undefined, dataLoading$); - expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( - UnifiedHistogramFetchStatus.loading, - undefined - ); - expect(props.onChartLoad).toHaveBeenLastCalledWith({ adapters: {}, dataLoading$ }); - expect(buildBucketInterval.buildBucketInterval).not.toHaveBeenCalled(); - expect(useTimeRange.useTimeRange).toHaveBeenLastCalledWith( - expect.objectContaining({ bucketInterval: undefined }) - ); + expect(props.onLoad).toHaveBeenLastCalledWith(true, undefined, dataLoading$); act(() => { onLoad?.(false, adapters, dataLoading$); }); - expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( - UnifiedHistogramFetchStatus.complete, - 100 - ); - expect(props.onChartLoad).toHaveBeenLastCalledWith({ adapters, dataLoading$ }); - expect(buildBucketInterval.buildBucketInterval).toHaveBeenCalled(); - expect(useTimeRange.useTimeRange).toHaveBeenLastCalledWith( - expect.objectContaining({ bucketInterval: mockBucketInterval }) - ); + expect(props.onLoad).toHaveBeenLastCalledWith(false, adapters, dataLoading$); }); it('should execute onLoad correctly when the request has a failure status', async () => { @@ -206,11 +186,7 @@ describe('Histogram', () => { .spyOn(adapters.requests, 'getRequests') .mockReturnValue([{ status: RequestStatus.ERROR } as any]); onLoad?.(false, adapters); - expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( - UnifiedHistogramFetchStatus.error, - undefined - ); - expect(props.onChartLoad).toHaveBeenLastCalledWith({ adapters }); + expect(props.onLoad).toHaveBeenLastCalledWith(false, adapters); }); it('should execute onLoad correctly when the response has shard failures', async () => { @@ -239,11 +215,7 @@ describe('Histogram', () => { act(() => { onLoad?.(false, adapters); }); - expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( - UnifiedHistogramFetchStatus.error, - 100 - ); - expect(props.onChartLoad).toHaveBeenLastCalledWith({ adapters }); + expect(props.onLoad).toHaveBeenLastCalledWith(false, adapters); }); it('should execute onLoad correctly for textbased language and no Lens suggestions', async () => { @@ -275,11 +247,7 @@ describe('Histogram', () => { act(() => { onLoad?.(false, adapters); }); - expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( - UnifiedHistogramFetchStatus.complete, - 20 - ); - expect(props.onChartLoad).toHaveBeenLastCalledWith({ adapters }); + expect(props.onLoad).toHaveBeenLastCalledWith(false, adapters); }); it('should execute onLoad correctly for textbased language and Lens suggestions', async () => { @@ -311,10 +279,6 @@ describe('Histogram', () => { act(() => { onLoad?.(false, adapters); }); - expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( - UnifiedHistogramFetchStatus.complete, - 2 - ); - expect(props.onChartLoad).toHaveBeenLastCalledWith({ adapters }); + expect(props.onLoad).toHaveBeenLastCalledWith(false, adapters); }); }); diff --git a/src/platform/plugins/shared/unified_histogram/public/chart/histogram.tsx b/src/platform/plugins/shared/unified_histogram/public/chart/histogram.tsx index 19f92d8b4495a..ad35f6141b4b7 100644 --- a/src/platform/plugins/shared/unified_histogram/public/chart/histogram.tsx +++ b/src/platform/plugins/shared/unified_histogram/public/chart/histogram.tsx @@ -9,101 +9,54 @@ import { useEuiTheme } from '@elastic/eui'; import { css } from '@emotion/react'; -import React, { useState } from 'react'; +import React from 'react'; import type { DataView } from '@kbn/data-views-plugin/public'; -import type { DefaultInspectorAdapters, Datatable } from '@kbn/expressions-plugin/common'; -import type { IKibanaSearchResponse } from '@kbn/search-types'; -import type { estypes } from '@elastic/elasticsearch'; import type { TimeRange } from '@kbn/es-query'; import type { EmbeddableComponentProps, LensEmbeddableInput } from '@kbn/lens-plugin/public'; -import { RequestStatus } from '@kbn/inspector-plugin/public'; -import type { Observable } from 'rxjs'; -import { PublishingSubject } from '@kbn/presentation-publishing'; -import { +import type { UnifiedHistogramBucketInterval, UnifiedHistogramChartContext, - UnifiedHistogramFetchStatus, - UnifiedHistogramHitsContext, - UnifiedHistogramChartLoadEvent, - UnifiedHistogramRequestContext, UnifiedHistogramServices, - UnifiedHistogramInputMessage, UnifiedHistogramVisContext, } from '../types'; -import { buildBucketInterval } from './utils/build_bucket_interval'; import { useTimeRange } from './hooks/use_time_range'; -import { useStableCallback } from '../hooks/use_stable_callback'; -import { useLensProps } from './hooks/use_lens_props'; +import type { LensProps } from './hooks/use_lens_props'; export interface HistogramProps { abortController?: AbortController; services: UnifiedHistogramServices; dataView: DataView; - request?: UnifiedHistogramRequestContext; - hits?: UnifiedHistogramHitsContext; chart: UnifiedHistogramChartContext; + bucketInterval?: UnifiedHistogramBucketInterval; isPlainRecord?: boolean; - hasLensSuggestions: boolean; getTimeRange: () => TimeRange; - refetch$: Observable; + requestData: string; + lensProps: LensProps; visContext: UnifiedHistogramVisContext; disableTriggers?: LensEmbeddableInput['disableTriggers']; disabledActions?: LensEmbeddableInput['disabledActions']; - onTotalHitsChange?: (status: UnifiedHistogramFetchStatus, result?: number | Error) => void; - onChartLoad?: (event: UnifiedHistogramChartLoadEvent) => void; onFilter?: LensEmbeddableInput['onFilter']; onBrushEnd?: LensEmbeddableInput['onBrushEnd']; withDefaultActions: EmbeddableComponentProps['withDefaultActions']; } -const computeTotalHits = ( - hasLensSuggestions: boolean, - adapterTables: - | { - [key: string]: Datatable; - } - | undefined, - isPlainRecord?: boolean -) => { - if (isPlainRecord && hasLensSuggestions) { - return Object.values(adapterTables ?? {})?.[0]?.rows?.length; - } else if (isPlainRecord && !hasLensSuggestions) { - // ES|QL histogram case - const rows = Object.values(adapterTables ?? {})?.[0]?.rows; - if (!rows) { - return undefined; - } - let rowsCount = 0; - rows.forEach((r) => { - rowsCount += r.results; - }); - return rowsCount; - } else { - return adapterTables?.unifiedHistogram?.meta?.statistics?.totalCount; - } -}; - export function Histogram({ - services: { data, lens, uiSettings }, + services: { lens, uiSettings }, dataView, - request, - hits, chart: { timeInterval }, + bucketInterval, isPlainRecord, - hasLensSuggestions, getTimeRange, - refetch$, + requestData, + lensProps, visContext, disableTriggers, disabledActions, - onTotalHitsChange, - onChartLoad, onFilter, onBrushEnd, withDefaultActions, abortController, }: HistogramProps) { - const [bucketInterval, setBucketInterval] = useState(); const { timeRangeText, timeRangeDisplay } = useTimeRange({ uiSettings, bucketInterval, @@ -113,63 +66,8 @@ export function Histogram({ timeField: dataView.timeFieldName, }); const { attributes } = visContext; - - const onLoad = useStableCallback( - ( - isLoading: boolean, - adapters: Partial | undefined, - dataLoading$?: PublishingSubject - ) => { - const lensRequest = adapters?.requests?.getRequests()[0]; - const requestFailed = lensRequest?.status === RequestStatus.ERROR; - const json = lensRequest?.response?.json as - | IKibanaSearchResponse - | undefined; - const response = json?.rawResponse; - - if (requestFailed) { - onTotalHitsChange?.(UnifiedHistogramFetchStatus.error, undefined); - onChartLoad?.({ adapters: adapters ?? {} }); - return; - } - - const adapterTables = adapters?.tables?.tables; - const totalHits = computeTotalHits(hasLensSuggestions, adapterTables, isPlainRecord); - - if (response?._shards?.failed || response?.timed_out) { - onTotalHitsChange?.(UnifiedHistogramFetchStatus.error, totalHits); - } else { - onTotalHitsChange?.( - isLoading ? UnifiedHistogramFetchStatus.loading : UnifiedHistogramFetchStatus.complete, - totalHits ?? hits?.total - ); - } - - if (response) { - const newBucketInterval = buildBucketInterval({ - data, - dataView, - timeInterval, - timeRange: getTimeRange(), - response, - }); - - setBucketInterval(newBucketInterval); - } - - onChartLoad?.({ adapters: adapters ?? {}, dataLoading$ }); - } - ); - - const { lensProps, requestData } = useLensProps({ - request, - getTimeRange, - refetch$, - visContext, - onLoad, - }); - const { euiTheme } = useEuiTheme(); + const boxShadow = `0 2px 2px -1px ${euiTheme.colors.mediumShade}, 0 1px 5px -2px ${euiTheme.colors.mediumShade}`; const chartCss = css` diff --git a/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_fetch.test.ts b/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_fetch.test.ts new file mode 100644 index 0000000000000..d8be832908e0d --- /dev/null +++ b/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_fetch.test.ts @@ -0,0 +1,35 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { useFetch } from './use_fetch'; +import { renderHook } from '@testing-library/react'; +import { UnifiedHistogramInput$ } from '../../types'; +import { Subject } from 'rxjs'; + +describe('useFetch', () => { + const getDeps: () => { + input$: UnifiedHistogramInput$; + beforeFetch: () => void; + } = () => ({ + input$: new Subject(), + beforeFetch: () => {}, + }); + + it('should trigger the fetch observable when the input$ observable is triggered', () => { + const originalDeps = getDeps(); + const hook = renderHook((deps) => useFetch(deps), { + initialProps: originalDeps, + }); + const fetch = jest.fn(); + hook.result.current.subscribe(fetch); + expect(fetch).not.toHaveBeenCalled(); + originalDeps.input$.next({ type: 'fetch' }); + expect(fetch).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_fetch.ts b/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_fetch.ts new file mode 100644 index 0000000000000..e48d1026a9d3a --- /dev/null +++ b/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_fetch.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { useMemo } from 'react'; +import { filter, share, tap } from 'rxjs'; +import { UnifiedHistogramInput$ } from '../../types'; + +export const useFetch = ({ + input$, + beforeFetch, +}: { + input$: UnifiedHistogramInput$; + beforeFetch: () => void; +}) => { + return useMemo( + () => + input$.pipe( + filter((message) => message.type === 'fetch'), + tap(beforeFetch), + share() + ), + [beforeFetch, input$] + ); +}; diff --git a/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_lens_props.test.ts b/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_lens_props.test.ts index d66856bdb4f0d..8ec349b7ee85a 100644 --- a/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_lens_props.test.ts +++ b/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_lens_props.test.ts @@ -17,7 +17,7 @@ import { getLensProps, useLensProps } from './use_lens_props'; describe('useLensProps', () => { it('should return lens props', async () => { const getTimeRange = jest.fn(); - const refetch$ = new Subject(); + const fetch$ = new Subject(); const onLoad = jest.fn(); const query = { language: 'kuery', @@ -41,12 +41,15 @@ describe('useLensProps', () => { adapter: undefined, }, getTimeRange, - refetch$, + fetch$, visContext: attributesContext!, onLoad, }); }); - expect(lensProps.result.current.lensProps).toEqual( + act(() => { + fetch$.next({ type: 'fetch' }); + }); + expect(lensProps.result.current?.lensProps).toEqual( getLensProps({ searchSessionId: 'id', getTimeRange, @@ -58,7 +61,7 @@ describe('useLensProps', () => { it('should return lens props for text based languages', async () => { const getTimeRange = jest.fn(); - const refetch$ = new Subject(); + const fetch$ = new Subject(); const onLoad = jest.fn(); const query = { language: 'kuery', @@ -82,12 +85,15 @@ describe('useLensProps', () => { adapter: undefined, }, getTimeRange, - refetch$, + fetch$, visContext: attributesContext!, onLoad, }); }); - expect(lensProps.result.current.lensProps).toEqual( + act(() => { + fetch$.next({ type: 'fetch' }); + }); + expect(lensProps.result.current?.lensProps).toEqual( getLensProps({ searchSessionId: 'id', getTimeRange, @@ -97,9 +103,9 @@ describe('useLensProps', () => { ); }); - it('should only update lens props when refetch$ is triggered', async () => { + it('should only return lens props after fetch$ is triggered', async () => { const getTimeRange = jest.fn(); - const refetch$ = new Subject(); + const fetch$ = new Subject(); const onLoad = jest.fn(); const query = { language: 'kuery', @@ -122,7 +128,7 @@ describe('useLensProps', () => { adapter: undefined, }, getTimeRange, - refetch$, + fetch$, visContext: attributesContext!, onLoad, }; @@ -132,12 +138,12 @@ describe('useLensProps', () => { }, { initialProps: lensProps } ); - const originalProps = hook.result.current; + expect(hook.result.current).toEqual(undefined); hook.rerender({ ...lensProps, request: { searchSessionId: '456', adapter: undefined } }); - expect(hook.result.current).toEqual(originalProps); + expect(hook.result.current).toEqual(undefined); act(() => { - refetch$.next({ type: 'refetch' }); + fetch$.next({ type: 'fetch' }); }); - expect(hook.result.current).not.toEqual(originalProps); + expect(hook.result.current).not.toEqual(undefined); }); }); diff --git a/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_lens_props.ts b/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_lens_props.ts index 155a38ea9a0ab..8cf2af38b8353 100644 --- a/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_lens_props.ts +++ b/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_lens_props.ts @@ -10,7 +10,7 @@ import type { TimeRange } from '@kbn/data-plugin/common'; import { ViewMode } from '@kbn/embeddable-plugin/public'; import type { DefaultInspectorAdapters } from '@kbn/expressions-plugin/common'; -import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; +import type { EmbeddableComponentProps, TypedLensByValueInput } from '@kbn/lens-plugin/public'; import { useCallback, useEffect, useState } from 'react'; import type { Observable } from 'rxjs'; import type { @@ -20,21 +20,38 @@ import type { } from '../../types'; import { useStableCallback } from '../../hooks/use_stable_callback'; +export type LensProps = Pick< + EmbeddableComponentProps, + | 'id' + | 'viewMode' + | 'timeRange' + | 'attributes' + | 'noPadding' + | 'searchSessionId' + | 'executionContext' + | 'onLoad' +>; + export const useLensProps = ({ request, getTimeRange, - refetch$, + fetch$, visContext, onLoad, }: { request?: UnifiedHistogramRequestContext; getTimeRange: () => TimeRange; - refetch$: Observable; - visContext: UnifiedHistogramVisContext; + fetch$: Observable; + visContext?: UnifiedHistogramVisContext; onLoad: (isLoading: boolean, adapters: Partial | undefined) => void; }) => { const buildLensProps = useCallback(() => { + if (!visContext) { + return; + } + const { attributes, requestData } = visContext; + return { requestData: JSON.stringify(requestData), lensProps: getLensProps({ @@ -46,13 +63,14 @@ export const useLensProps = ({ }; }, [visContext, getTimeRange, onLoad, request?.searchSessionId]); - const [lensPropsContext, setLensPropsContext] = useState(buildLensProps()); + // Initialize with undefined to avoid rendering Lens until a fetch has been triggered + const [lensPropsContext, setLensPropsContext] = useState>(); const updateLensPropsContext = useStableCallback(() => setLensPropsContext(buildLensProps())); useEffect(() => { - const subscription = refetch$.subscribe(updateLensPropsContext); + const subscription = fetch$.subscribe(updateLensPropsContext); return () => subscription.unsubscribe(); - }, [refetch$, updateLensPropsContext]); + }, [fetch$, updateLensPropsContext]); return lensPropsContext; }; @@ -67,7 +85,7 @@ export const getLensProps = ({ getTimeRange: () => TimeRange; attributes: TypedLensByValueInput['attributes']; onLoad: (isLoading: boolean, adapters: Partial | undefined) => void; -}) => ({ +}): LensProps => ({ id: 'unifiedHistogramLensComponent', viewMode: ViewMode.VIEW, timeRange: getTimeRange(), diff --git a/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_refetch.test.ts b/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_refetch.test.ts deleted file mode 100644 index cf8590009062b..0000000000000 --- a/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_refetch.test.ts +++ /dev/null @@ -1,86 +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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { useRefetch } from './use_refetch'; -import { DataView } from '@kbn/data-views-plugin/common'; -import { AggregateQuery, Filter, Query, TimeRange } from '@kbn/es-query'; -import { renderHook } from '@testing-library/react'; -import { - UnifiedHistogramBreakdownContext, - UnifiedHistogramChartContext, - UnifiedHistogramHitsContext, - UnifiedHistogramInput$, - UnifiedHistogramRequestContext, -} from '../../types'; -import { dataViewWithTimefieldMock } from '../../__mocks__/data_view_with_timefield'; -import { Subject } from 'rxjs'; - -describe('useRefetch', () => { - const getDeps: () => { - dataView: DataView; - request: UnifiedHistogramRequestContext | undefined; - hits: UnifiedHistogramHitsContext | undefined; - chart: UnifiedHistogramChartContext | undefined; - chartVisible: boolean; - breakdown: UnifiedHistogramBreakdownContext | undefined; - filters: Filter[]; - query: Query | AggregateQuery; - relativeTimeRange: TimeRange; - input$: UnifiedHistogramInput$; - beforeRefetch: () => void; - } = () => ({ - dataView: dataViewWithTimefieldMock, - request: undefined, - hits: undefined, - chart: undefined, - chartVisible: true, - breakdown: undefined, - filters: [], - query: { language: 'kuery', query: '' }, - relativeTimeRange: { from: 'now-15m', to: 'now' }, - input$: new Subject(), - beforeRefetch: () => {}, - }); - - it('should trigger the refetch observable when any of the arguments change', () => { - const originalDeps = getDeps(); - const hook = renderHook((deps) => useRefetch(deps), { - initialProps: originalDeps, - }); - const refetch = jest.fn(); - hook.result.current.subscribe(refetch); - hook.rerender({ ...originalDeps }); - expect(refetch).not.toHaveBeenCalled(); - hook.rerender({ ...originalDeps, chartVisible: false }); - expect(refetch).toHaveBeenCalledTimes(1); - }); - - it('should not trigger the refetch observable when disableAutoFetching is true', () => { - const originalDeps = { ...getDeps(), disableAutoFetching: true }; - const hook = renderHook((deps) => useRefetch(deps), { - initialProps: originalDeps, - }); - const refetch = jest.fn(); - hook.result.current.subscribe(refetch); - hook.rerender({ ...originalDeps, chartVisible: false }); - expect(refetch).not.toHaveBeenCalled(); - }); - - it('should trigger the refetch observable when the input$ observable is triggered', () => { - const originalDeps = { ...getDeps(), disableAutoFetching: true }; - const hook = renderHook((deps) => useRefetch(deps), { - initialProps: originalDeps, - }); - const refetch = jest.fn(); - hook.result.current.subscribe(refetch); - expect(refetch).not.toHaveBeenCalled(); - originalDeps.input$.next({ type: 'refetch' }); - expect(refetch).toHaveBeenCalledTimes(1); - }); -}); diff --git a/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_refetch.ts b/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_refetch.ts deleted file mode 100644 index 07abcae6c3c45..0000000000000 --- a/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_refetch.ts +++ /dev/null @@ -1,145 +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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { DataView } from '@kbn/data-views-plugin/common'; -import type { AggregateQuery, Filter, Query, TimeRange } from '@kbn/es-query'; -import type { Suggestion } from '@kbn/lens-plugin/public'; -import { cloneDeep, isEqual } from 'lodash'; -import { useEffect, useMemo, useRef } from 'react'; -import { filter, share, tap } from 'rxjs'; -import { - UnifiedHistogramBreakdownContext, - UnifiedHistogramChartContext, - UnifiedHistogramHitsContext, - UnifiedHistogramInput$, - UnifiedHistogramRequestContext, -} from '../../types'; - -export const useRefetch = ({ - dataView, - request, - hits, - chart, - chartVisible, - breakdown, - filters, - query, - relativeTimeRange, - currentSuggestion, - disableAutoFetching, - input$, - beforeRefetch, -}: { - dataView: DataView; - request: UnifiedHistogramRequestContext | undefined; - hits: UnifiedHistogramHitsContext | undefined; - chart: UnifiedHistogramChartContext | undefined; - chartVisible: boolean; - breakdown: UnifiedHistogramBreakdownContext | undefined; - filters: Filter[]; - query: Query | AggregateQuery; - relativeTimeRange: TimeRange; - currentSuggestion?: Suggestion; - disableAutoFetching?: boolean; - input$: UnifiedHistogramInput$; - beforeRefetch: () => void; -}) => { - const refetchDeps = useRef>(); - - // When the Unified Histogram props change, we must compare the current subset - // that should trigger a histogram refetch against the previous subset. If they - // are different, we must refetch the histogram to ensure it's up to date. - useEffect(() => { - // Skip if auto fetching if disabled - if (disableAutoFetching) { - return; - } - - const newRefetchDeps = getRefetchDeps({ - dataView, - request, - hits, - chart, - chartVisible, - breakdown, - filters, - query, - relativeTimeRange, - currentSuggestion, - }); - - if (!isEqual(refetchDeps.current, newRefetchDeps)) { - if (refetchDeps.current) { - input$.next({ type: 'refetch' }); - } - - refetchDeps.current = newRefetchDeps; - } - }, [ - breakdown, - chart, - chartVisible, - currentSuggestion, - dataView, - disableAutoFetching, - filters, - hits, - input$, - query, - relativeTimeRange, - request, - ]); - - return useMemo( - () => - input$.pipe( - filter((message) => message.type === 'refetch'), - tap(beforeRefetch), - share() - ), - [beforeRefetch, input$] - ); -}; - -const getRefetchDeps = ({ - dataView, - request, - hits, - chart, - chartVisible, - breakdown, - filters, - query, - relativeTimeRange, - currentSuggestion, -}: { - dataView: DataView; - request: UnifiedHistogramRequestContext | undefined; - hits: UnifiedHistogramHitsContext | undefined; - chart: UnifiedHistogramChartContext | undefined; - chartVisible: boolean; - breakdown: UnifiedHistogramBreakdownContext | undefined; - filters: Filter[]; - query: Query | AggregateQuery; - relativeTimeRange: TimeRange; - currentSuggestion?: Suggestion; -}) => - cloneDeep([ - dataView.id, - request?.searchSessionId, - Boolean(hits), - chartVisible, - chart?.timeInterval, - Boolean(breakdown), - breakdown?.field, - filters, - query, - relativeTimeRange, - currentSuggestion?.visualizationId, - ]); diff --git a/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_total_hits.test.ts b/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_total_hits.test.ts index 4ba57d490db6f..9f7c1ef4c118d 100644 --- a/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_total_hits.test.ts +++ b/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_total_hits.test.ts @@ -28,7 +28,7 @@ jest.mock('react-use/lib/useDebounce', () => { describe('useTotalHits', () => { const timeRange = { from: 'now-15m', to: 'now' }; - const refetch$: UnifiedHistogramInput$ = new Subject(); + const fetch$: UnifiedHistogramInput$ = new Subject(); const getDeps = () => ({ services: { data: dataPluginMock.createStartContract(), @@ -54,7 +54,7 @@ describe('useTotalHits', () => { filters: [], query: { query: '', language: 'kuery' }, getTimeRange: () => timeRange, - refetch$, + fetch$, onTotalHitsChange: jest.fn(), }); @@ -95,11 +95,11 @@ describe('useTotalHits', () => { }, query, filters, - refetch$, + fetch$, onTotalHitsChange, }) ); - refetch$.next({ type: 'refetch' }); + fetch$.next({ type: 'fetch' }); rerender(); expect(onTotalHitsChange).toBeCalledTimes(1); expect(onTotalHitsChange).toBeCalledWith(UnifiedHistogramFetchStatus.loading, undefined); @@ -128,7 +128,7 @@ describe('useTotalHits', () => { query: { esql: 'from test' }, }; const { rerender } = renderHook(() => useTotalHits(deps)); - refetch$.next({ type: 'refetch' }); + fetch$.next({ type: 'fetch' }); rerender(); expect(onTotalHitsChange).not.toHaveBeenCalled(); }); @@ -153,7 +153,7 @@ describe('useTotalHits', () => { expect(fetchSpy).not.toHaveBeenCalled(); }); - it('should not fetch if refetch$ is not triggered', async () => { + it('should not fetch if fetch$ is not triggered', async () => { const onTotalHitsChange = jest.fn(); const fetchSpy = jest.spyOn(searchSourceInstanceMock, 'fetch$').mockClear(); const setFieldSpy = jest.spyOn(searchSourceInstanceMock, 'setField').mockClear(); @@ -165,14 +165,14 @@ describe('useTotalHits', () => { expect(fetchSpy).toHaveBeenCalledTimes(0); }); - it('should fetch a second time if refetch$ is triggered', async () => { + it('should fetch a second time if fetch$ is triggered', async () => { const abortSpy = jest.spyOn(AbortController.prototype, 'abort').mockClear(); const onTotalHitsChange = jest.fn(); const fetchSpy = jest.spyOn(searchSourceInstanceMock, 'fetch$').mockClear(); const setFieldSpy = jest.spyOn(searchSourceInstanceMock, 'setField').mockClear(); const options = { ...getDeps(), onTotalHitsChange }; const { rerender } = renderHook(() => useTotalHits(options)); - refetch$.next({ type: 'refetch' }); + fetch$.next({ type: 'fetch' }); rerender(); expect(onTotalHitsChange).toBeCalledTimes(1); expect(setFieldSpy).toHaveBeenCalled(); @@ -180,7 +180,7 @@ describe('useTotalHits', () => { await waitFor(() => { expect(onTotalHitsChange).toBeCalledTimes(2); }); - refetch$.next({ type: 'refetch' }); + fetch$.next({ type: 'fetch' }); rerender(); expect(abortSpy).toHaveBeenCalled(); expect(onTotalHitsChange).toBeCalledTimes(3); @@ -199,7 +199,7 @@ describe('useTotalHits', () => { .mockClear() .mockReturnValue(throwError(() => error)); const { rerender } = renderHook(() => useTotalHits({ ...getDeps(), onTotalHitsChange })); - refetch$.next({ type: 'refetch' }); + fetch$.next({ type: 'fetch' }); rerender(); await waitFor(() => { expect(onTotalHitsChange).toBeCalledTimes(2); @@ -228,7 +228,7 @@ describe('useTotalHits', () => { filters, }) ); - refetch$.next({ type: 'refetch' }); + fetch$.next({ type: 'fetch' }); rerender(); expect(setOverwriteDataViewTypeSpy).toHaveBeenCalledWith(undefined); expect(setFieldSpy).toHaveBeenCalledWith('filter', filters); diff --git a/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_total_hits.ts b/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_total_hits.ts index 1399074816903..5f338c8500b3f 100644 --- a/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_total_hits.ts +++ b/src/platform/plugins/shared/unified_histogram/public/chart/hooks/use_total_hits.ts @@ -31,7 +31,7 @@ export const useTotalHits = ({ filters, query, getTimeRange, - refetch$, + fetch$, onTotalHitsChange, isPlainRecord, }: { @@ -43,7 +43,7 @@ export const useTotalHits = ({ filters: Filter[]; query: Query | AggregateQuery; getTimeRange: () => TimeRange; - refetch$: Observable; + fetch$: Observable; onTotalHitsChange?: (status: UnifiedHistogramFetchStatus, result?: number | Error) => void; isPlainRecord?: boolean; }) => { @@ -65,9 +65,9 @@ export const useTotalHits = ({ }); useEffect(() => { - const subscription = refetch$.subscribe(fetch); + const subscription = fetch$.subscribe(fetch); return () => subscription.unsubscribe(); - }, [fetch, refetch$]); + }, [fetch, fetch$]); }; const fetchTotalHits = async ({ diff --git a/src/platform/plugins/shared/unified_histogram/public/container/container.test.tsx b/src/platform/plugins/shared/unified_histogram/public/container/container.test.tsx index 4f499cfbb58fa..d67d4fc4fd815 100644 --- a/src/platform/plugins/shared/unified_histogram/public/container/container.test.tsx +++ b/src/platform/plugins/shared/unified_histogram/public/container/container.test.tsx @@ -46,17 +46,15 @@ describe('UnifiedHistogramContainer', () => { expect(api).toBeDefined(); }); - it('should trigger input$ when refetch is called', async () => { + it('should trigger input$ when fetch is called', async () => { let api: UnifiedHistogramApi | undefined; const setApi = (ref: UnifiedHistogramApi) => { api = ref; }; - const getCreationOptions = jest.fn(() => ({ disableAutoFetching: true })); const component = mountWithIntl( { const inputSpy = jest.fn(); input$?.subscribe(inputSpy); act(() => { - api?.refetch(); + api?.fetch(); }); expect(inputSpy).toHaveBeenCalledTimes(1); - expect(inputSpy).toHaveBeenCalledWith({ type: 'refetch' }); + expect(inputSpy).toHaveBeenCalledWith({ type: 'fetch' }); }); }); diff --git a/src/platform/plugins/shared/unified_histogram/public/container/container.tsx b/src/platform/plugins/shared/unified_histogram/public/container/container.tsx index ce55d0773344e..5d83f8e84101a 100644 --- a/src/platform/plugins/shared/unified_histogram/public/container/container.tsx +++ b/src/platform/plugins/shared/unified_histogram/public/container/container.tsx @@ -30,10 +30,7 @@ import { topPanelHeightSelector } from './utils/state_selectors'; import { exportVisContext } from '../utils/external_vis_context'; import { getBreakdownField } from './utils/local_storage_utils'; -type LayoutProps = Pick< - UnifiedHistogramLayoutProps, - 'disableAutoFetching' | 'disableTriggers' | 'disabledActions' ->; +type LayoutProps = Pick; /** * The options used to initialize the container @@ -84,9 +81,9 @@ export type UnifiedHistogramContainerProps = { */ export type UnifiedHistogramApi = { /** - * Manually trigger a refetch of the data + * Trigger a fetch of the data */ - refetch: () => void; + fetch: () => void; } & Pick< UnifiedHistogramStateService, 'state$' | 'setChartHidden' | 'setTopPanelHeight' | 'setTimeInterval' | 'setTotalHits' @@ -112,7 +109,7 @@ export const UnifiedHistogramContainer = forwardRef< const options = await getCreationOptions?.(); const apiHelper = await services.lens.stateHelperApi(); - setLayoutProps(pick(options, 'disableAutoFetching', 'disableTriggers', 'disabledActions')); + setLayoutProps(pick(options, 'disableTriggers', 'disabledActions')); setLocalStorageKeyPrefix(options?.localStorageKeyPrefix); setStateService(createStateService({ services, ...options })); setLensSuggestionsApi(() => apiHelper.suggestions); @@ -125,8 +122,8 @@ export const UnifiedHistogramContainer = forwardRef< } setApi({ - refetch: () => { - input$.next({ type: 'refetch' }); + fetch: () => { + input$.next({ type: 'fetch' }); }, ...pick( stateService, diff --git a/src/platform/plugins/shared/unified_histogram/public/layout/layout.tsx b/src/platform/plugins/shared/unified_histogram/public/layout/layout.tsx index b9d9f6fbc446f..c384102ed1691 100644 --- a/src/platform/plugins/shared/unified_histogram/public/layout/layout.tsx +++ b/src/platform/plugins/shared/unified_histogram/public/layout/layout.tsx @@ -119,10 +119,6 @@ export interface UnifiedHistogramLayoutProps extends PropsWithChildren * This element would replace the default chart toggle buttons */ renderCustomChartToggleActions?: () => ReactElement | undefined; - /** - * Disable automatic refetching based on props changes, and instead wait for a `refetch` message - */ - disableAutoFetching?: boolean; /** * Disable triggers for the Lens embeddable */ @@ -219,7 +215,6 @@ export const UnifiedHistogramLayout = ({ container, topPanelHeight, renderCustomChartToggleActions, - disableAutoFetching, disableTriggers, disabledActions, lensSuggestionsApi, @@ -359,7 +354,6 @@ export const UnifiedHistogramLayout = ({ breakdown={breakdown} renderCustomChartToggleActions={renderCustomChartToggleActions} appendHistogram={chartSpacer} - disableAutoFetching={disableAutoFetching} disableTriggers={disableTriggers} disabledActions={disabledActions} input$={input$} diff --git a/src/platform/plugins/shared/unified_histogram/public/mocks.ts b/src/platform/plugins/shared/unified_histogram/public/mocks.ts index 11ebd50239257..73d7d2bd93015 100644 --- a/src/platform/plugins/shared/unified_histogram/public/mocks.ts +++ b/src/platform/plugins/shared/unified_histogram/public/mocks.ts @@ -17,7 +17,7 @@ export const createMockUnifiedHistogramApi = () => { setTopPanelHeight: jest.fn(), setTimeInterval: jest.fn(), setTotalHits: jest.fn(), - refetch: jest.fn(), + fetch: jest.fn(), }; return api; }; diff --git a/src/platform/plugins/shared/unified_histogram/public/types.ts b/src/platform/plugins/shared/unified_histogram/public/types.ts index a64000da11df0..47881249089ec 100644 --- a/src/platform/plugins/shared/unified_histogram/public/types.ts +++ b/src/platform/plugins/shared/unified_histogram/public/types.ts @@ -126,16 +126,16 @@ export interface UnifiedHistogramBreakdownContext { } /** - * Message to refetch the chart and total hits + * Message to fetch the chart and total hits */ -export interface UnifiedHistogramRefetchMessage { - type: 'refetch'; +export interface UnifiedHistogramFetchMessage { + type: 'fetch'; } /** * Unified histogram input message */ -export type UnifiedHistogramInputMessage = UnifiedHistogramRefetchMessage; +export type UnifiedHistogramInputMessage = UnifiedHistogramFetchMessage; /** * Unified histogram input observable diff --git a/src/platform/plugins/shared/visualizations/public/embeddable/state.test.ts b/src/platform/plugins/shared/visualizations/public/embeddable/state.test.ts index b6075b9153bef..bda5bb18d0edb 100644 --- a/src/platform/plugins/shared/visualizations/public/embeddable/state.test.ts +++ b/src/platform/plugins/shared/visualizations/public/embeddable/state.test.ts @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { SerializedPanelState } from '@kbn/presentation-containers'; +import { SerializedPanelState } from '@kbn/presentation-publishing'; import { serializeState, deserializeSavedVisState } from './state'; import { VisualizeSavedVisInputState } from './types'; diff --git a/src/platform/plugins/shared/visualizations/public/embeddable/state.ts b/src/platform/plugins/shared/visualizations/public/embeddable/state.ts index 79a3bc841a999..2b1baea47c829 100644 --- a/src/platform/plugins/shared/visualizations/public/embeddable/state.ts +++ b/src/platform/plugins/shared/visualizations/public/embeddable/state.ts @@ -9,8 +9,7 @@ import type { SerializedSearchSourceFields } from '@kbn/data-plugin/public'; import { extractSearchSourceReferences } from '@kbn/data-plugin/public'; -import { SerializedPanelState } from '@kbn/presentation-containers'; -import { SerializedTitles } from '@kbn/presentation-publishing'; +import { SerializedTitles, SerializedPanelState } from '@kbn/presentation-publishing'; import { cloneDeep, isEmpty, omit } from 'lodash'; import { Reference } from '../../common/content_management'; import { diff --git a/src/platform/plugins/shared/visualizations/public/embeddable/types.ts b/src/platform/plugins/shared/visualizations/public/embeddable/types.ts index 767f911d5bd52..ad7a7c86dde58 100644 --- a/src/platform/plugins/shared/visualizations/public/embeddable/types.ts +++ b/src/platform/plugins/shared/visualizations/public/embeddable/types.ts @@ -14,6 +14,7 @@ import type { TimeRange } from '@kbn/es-query'; import { HasInspectorAdapters } from '@kbn/inspector-plugin/public'; import { HasEditCapabilities, + HasLibraryTransforms, HasSupportedTriggers, PublishesDataLoading, PublishesDataViews, @@ -98,13 +99,8 @@ export type VisualizeApi = Partial & HasInspectorAdapters & HasSupportedTriggers & PublishesTimeRange & + HasLibraryTransforms & DefaultEmbeddableApi & { updateVis: (vis: DeepPartial>) => void; openInspector: () => OverlayRef | undefined; - saveToLibrary: (title: string) => Promise; - canLinkToLibrary: () => boolean; - canUnlinkFromLibrary: () => boolean; - checkForDuplicateTitle: (title: string) => boolean; - getByValueState: () => VisualizeSerializedState; - getByReferenceState: (id: string) => VisualizeSerializedState; }; diff --git a/src/platform/plugins/shared/visualizations/public/embeddable/visualize_embeddable.tsx b/src/platform/plugins/shared/visualizations/public/embeddable/visualize_embeddable.tsx index 71338e96ea145..c1e069e370137 100644 --- a/src/platform/plugins/shared/visualizations/public/embeddable/visualize_embeddable.tsx +++ b/src/platform/plugins/shared/visualizations/public/embeddable/visualize_embeddable.tsx @@ -171,6 +171,22 @@ export const getVisualizeEmbeddableFactory: (deps: { const defaultPanelTitle = new BehaviorSubject(initialVisInstance.title); + const serializeVisualizeEmbeddable = ( + savedObjectId: string | undefined, + linkedToLibrary: boolean + ) => { + const savedObjectProperties = savedObjectProperties$.getValue(); + return serializeState({ + serializedVis: vis$.getValue().serialize(), + titles: serializeTitles(), + id: savedObjectId, + linkedToLibrary, + ...(savedObjectProperties ? { savedObjectProperties } : {}), + ...(dynamicActionsApi?.serializeDynamicActions?.() ?? {}), + ...serializeCustomTimeRange(), + }); + }; + const api = buildApi( { ...customTimeRangeApi, @@ -186,20 +202,13 @@ export const getVisualizeEmbeddableFactory: (deps: { SELECT_RANGE_TRIGGER, ], serializeState: () => { - const savedObjectProperties = savedObjectProperties$.getValue(); - return serializeState({ - serializedVis: vis$.getValue().serialize(), - titles: serializeTitles(), - id: savedObjectId$.getValue(), - linkedToLibrary: - // In the visualize editor, linkedToLibrary should always be false to force the full state to be serialized, - // instead of just passing a reference to the linked saved object. Other contexts like dashboards should - // serialize the state with just the savedObjectId so that the current revision of the vis is always used - apiIsOfType(parentApi, VISUALIZE_APP_NAME) ? false : linkedToLibrary$.getValue(), - ...(savedObjectProperties ? { savedObjectProperties } : {}), - ...(dynamicActionsApi?.serializeDynamicActions?.() ?? {}), - ...serializeCustomTimeRange(), - }); + // In the visualize editor, linkedToLibrary should always be false to force the full state to be serialized, + // instead of just passing a reference to the linked saved object. Other contexts like dashboards should + // serialize the state with just the savedObjectId so that the current revision of the vis is always used + const linkedToLibrary = apiIsOfType(parentApi, VISUALIZE_APP_NAME) + ? false + : linkedToLibrary$.getValue(); + return serializeVisualizeEmbeddable(savedObjectId$.getValue(), Boolean(linkedToLibrary)); }, getVis: () => vis$.getValue(), getInspectorAdapters: () => inspectorAdapters$.getValue(), @@ -260,20 +269,11 @@ export const getVisualizeEmbeddableFactory: (deps: { references, }); }, - canLinkToLibrary: () => !state.linkedToLibrary, - canUnlinkFromLibrary: () => !!state.linkedToLibrary, - checkForDuplicateTitle: () => false, // Handled by saveToLibrary action - getByValueState: () => ({ - savedVis: vis$.getValue().serialize(), - ...serializeTitles(), - }), - getByReferenceState: (libraryId) => - serializeState({ - serializedVis: vis$.getValue().serialize(), - titles: serializeTitles(), - id: libraryId, - linkedToLibrary: true, - }).rawState, + canLinkToLibrary: () => Promise.resolve(!state.linkedToLibrary), + canUnlinkFromLibrary: () => Promise.resolve(!!state.linkedToLibrary), + checkForDuplicateTitle: () => Promise.resolve(), // Handled by saveToLibrary action + getSerializedStateByValue: () => serializeVisualizeEmbeddable(undefined, false), + getSerializedStateByReference: (libraryId) => serializeVisualizeEmbeddable(libraryId, true), }, { ...titleComparators, diff --git a/test/functional/apps/dashboard_elements/links/links_create_edit.ts b/test/functional/apps/dashboard_elements/links/links_create_edit.ts index df930b42c2001..ac23b7e8747dc 100644 --- a/test/functional/apps/dashboard_elements/links/links_create_edit.ts +++ b/test/functional/apps/dashboard_elements/links/links_create_edit.ts @@ -77,7 +77,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await common.waitForSaveModalToClose(); await testSubjects.exists('addObjectToDashboardSuccess'); await testSubjects.existOrFail('links--component'); - await dashboardPanelActions.expectLinkedToLibrary(LINKS_PANEL_NAME, false); + await dashboardPanelActions.expectLinkedToLibrary(LINKS_PANEL_NAME); expect(await dashboardLinks.getNumberOfLinksInPanel()).to.equal(4); await dashboard.clickDiscardChanges(); diff --git a/test/functional/apps/discover/group3/_request_counts.ts b/test/functional/apps/discover/group3/_request_counts.ts index e44b0de22cb28..b025f23797228 100644 --- a/test/functional/apps/discover/group3/_request_counts.ts +++ b/test/functional/apps/discover/group3/_request_counts.ts @@ -65,11 +65,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { .getEntries() .filter((entry: any) => ['fetch', 'xmlhttprequest'].includes(entry.initiatorType)) ); - const result = requests.filter((entry) => entry.name.endsWith(`/internal/search/${endpoint}`) ); - const count = result.length; if (count !== searchCount) { log.warning('Request count differs:', result); @@ -80,18 +78,18 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); }; - const waitForLoadingToFinish = async () => { - await header.waitUntilLoadingHasFinished(); - await discover.waitForDocTableLoadingComplete(); - await elasticChart.canvasExists(); - }; - const expectSearches = async (type: 'ese' | 'esql', expected: number, cb: Function) => { await expectSearchCount(type, 0); await cb(); await expectSearchCount(type, expected); }; + const waitForLoadingToFinish = async () => { + await header.waitUntilLoadingHasFinished(); + await discover.waitForDocTableLoadingComplete(); + await elasticChart.canvasExists(); + }; + const getSharedTests = ({ type, savedSearch, @@ -99,7 +97,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { query2, savedSearchesRequests, setQuery, - expectedRequests = 2, }: { type: 'ese' | 'esql'; savedSearch: string; @@ -107,10 +104,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { query2: string; savedSearchesRequests?: number; setQuery: (query: string) => Promise; - expectedRequests?: number; - expectedRefreshRequest?: number; }) => { - it(`should send no more than ${expectedRequests} search requests (documents + chart) on page load`, async () => { + it(`should send 2 search requests (documents + chart) on page load`, async () => { if (type === 'ese') { await browser.refresh(); } @@ -118,29 +113,29 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { performance.setResourceTimingBufferSize(Number.MAX_SAFE_INTEGER); }); if (type === 'esql') { - await expectSearches(type, expectedRequests, async () => { + await expectSearches(type, 2, async () => { await queryBar.clickQuerySubmitButton(); }); } else { - await expectSearchCount(type, expectedRequests); + await expectSearchCount(type, 2); } }); - it(`should send no more than ${expectedRequests} requests (documents + chart) when refreshing`, async () => { - await expectSearches(type, expectedRequests, async () => { + it(`should send 2 requests (documents + chart) when refreshing`, async () => { + await expectSearches(type, 2, async () => { await queryBar.clickQuerySubmitButton(); }); }); - it(`should send no more than ${expectedRequests} requests (documents + chart) when changing the query`, async () => { - await expectSearches(type, expectedRequests, async () => { + it(`should send 2 requests (documents + chart) when changing the query`, async () => { + await expectSearches(type, 2, async () => { await setQuery(query1); await queryBar.clickQuerySubmitButton(); }); }); - it(`should send no more than ${expectedRequests} requests (documents + chart) when changing the time range`, async () => { - await expectSearches(type, expectedRequests, async () => { + it(`should send 2 requests (documents + chart) when changing the time range`, async () => { + await expectSearches(type, 2, async () => { await timePicker.setAbsoluteRange( 'Sep 21, 2015 @ 06:31:44.000', 'Sep 23, 2015 @ 00:00:00.000' @@ -148,7 +143,32 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - it(`should send ${savedSearchesRequests} requests for saved search changes`, async () => { + it(`should send no requests (documents + chart) when toggling the chart visibility`, async () => { + await expectSearches(type, 0, async () => { + // hide chart + await discover.toggleChartVisibility(); + // show chart + await discover.toggleChartVisibility(); + }); + }); + + it(`should send a request for chart data when toggling the chart visibility after a time range change`, async () => { + // hide chart + await discover.toggleChartVisibility(); + await timePicker.setAbsoluteRange( + 'Sep 21, 2015 @ 06:31:44.000', + 'Sep 24, 2015 @ 00:00:00.000' + ); + await waitForLoadingToFinish(); + await expectSearches(type, 1, async () => { + // show chart, we expect a request for the chart data, since the time range changed + await discover.toggleChartVisibility(); + }); + }); + + const actualSavedSearchRequests = savedSearchesRequests ?? 2; + + it(`should send no more than ${actualSavedSearchRequests} requests for saved search changes`, async () => { await setQuery(query1); await queryBar.clickQuerySubmitButton(); await timePicker.setAbsoluteRange( @@ -156,42 +176,29 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'Sep 23, 2015 @ 00:00:00.000' ); await waitForLoadingToFinish(); - const actualExpectedRequests = savedSearchesRequests ?? expectedRequests; log.debug('Creating saved search'); - await expectSearches( - type, - type === 'esql' ? actualExpectedRequests + 2 : actualExpectedRequests, - async () => { - await discover.saveSearch(savedSearch); - } - ); + await expectSearches(type, actualSavedSearchRequests, async () => { + await discover.saveSearch(savedSearch); + }); log.debug('Resetting saved search'); await setQuery(query2); await queryBar.clickQuerySubmitButton(); await waitForLoadingToFinish(); - await expectSearches(type, actualExpectedRequests, async () => { + await expectSearches(type, 2, async () => { await discover.revertUnsavedChanges(); }); log.debug('Clearing saved search'); - await expectSearches( - type, - type === 'esql' ? actualExpectedRequests + 1 : actualExpectedRequests, - async () => { - await testSubjects.click('discoverNewButton'); - if (type === 'esql') { - await queryBar.clickQuerySubmitButton(); - } - await waitForLoadingToFinish(); + await expectSearches(type, actualSavedSearchRequests, async () => { + await testSubjects.click('discoverNewButton'); + if (type === 'esql') { + await queryBar.clickQuerySubmitButton(); } - ); + await waitForLoadingToFinish(); + }); log.debug('Loading saved search'); - await expectSearches( - type, - type === 'esql' ? actualExpectedRequests + 2 : actualExpectedRequests, - async () => { - await discover.loadSavedSearch(savedSearch); - } - ); + await expectSearches(type, actualSavedSearchRequests, async () => { + await discover.loadSavedSearch(savedSearch); + }); }); }; @@ -211,16 +218,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { setQuery: (query) => queryBar.setQuery(query), }); - it(`should send no more than 2 requests (documents + chart) when toggling the chart visibility`, async () => { - await expectSearches(type, 2, async () => { - await discover.toggleChartVisibility(); - }); - await expectSearches(type, 2, async () => { - await discover.toggleChartVisibility(); - }); - }); - - it('should send no more than 2 requests (documents + chart) when adding a filter', async () => { + it('should send 2 requests (documents + chart) when adding a filter', async () => { await expectSearches(type, 2, async () => { await filterBar.addFilter({ field: 'extension', @@ -230,39 +228,41 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - it('should send no more than 2 requests (documents + chart) when sorting', async () => { + it('should send 2 requests (documents + chart) when sorting', async () => { await expectSearches(type, 2, async () => { await discover.clickFieldSort('@timestamp', 'Sort Old-New'); }); }); - it('should send no more than 2 requests (documents + chart) when changing to a breakdown field without an other bucket', async () => { + it('should send 2 requests (documents + chart) when changing to a breakdown field without an other bucket', async () => { await expectSearches(type, 2, async () => { await discover.chooseBreakdownField('type'); }); }); - it('should send no more than 3 requests (documents + chart + other bucket) when changing to a breakdown field with an other bucket', async () => { + it('should send 3 requests (documents + chart + other bucket) when changing to a breakdown field with an other bucket', async () => { await testSubjects.click('discoverNewButton'); await expectSearches(type, 3, async () => { await discover.chooseBreakdownField('extension.raw'); }); }); - it('should send no more than 2 requests (documents + chart) when changing the chart interval', async () => { + it('should send 2 requests (documents + chart) when changing the chart interval', async () => { await expectSearches(type, 2, async () => { await discover.setChartInterval('Day'); }); }); - it('should send no more than 2 requests (documents + chart) when changing the data view', async () => { + it('should send 2 requests (documents + chart) when changing the data view', async () => { await expectSearches(type, 2, async () => { await discover.selectIndexPattern('long-window-logstash-*'); }); }); }); + describe('ES|QL mode', () => { const type = 'esql'; + before(async () => { await kibanaServer.uiSettings.update({ 'discover:searchOnPageLoad': false, @@ -280,18 +280,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { savedSearch: 'esql test', query1: 'from logstash-* | where bytes > 1000 ', query2: 'from logstash-* | where bytes < 2000 ', - savedSearchesRequests: 2, + savedSearchesRequests: 3, setQuery: (query) => monacoEditor.setCodeEditorValue(query), - expectedRequests: 2, - }); - - it(`should send requests (documents + chart) when toggling the chart visibility`, async () => { - await expectSearches(type, 1, async () => { - await discover.toggleChartVisibility(); - }); - await expectSearches(type, 3, async () => { - await discover.toggleChartVisibility(); - }); }); }); }); diff --git a/test/functional/apps/visualize/group3/_add_to_dashboard.ts b/test/functional/apps/visualize/group3/_add_to_dashboard.ts index d0921f5ab1d7d..3f6c70d9ebb84 100644 --- a/test/functional/apps/visualize/group3/_add_to_dashboard.ts +++ b/test/functional/apps/visualize/group3/_add_to_dashboard.ts @@ -202,7 +202,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const panelCount = await dashboard.getPanelCount(); expect(panelCount).to.eql(2); - await dashboardPanelActions.expectLinkedToLibrary('My Saved New Vis 2', false); + await dashboardPanelActions.expectLinkedToLibrary('My Saved New Vis 2'); }); it('adding a existing metric to an existing dashboard by value', async function () { diff --git a/test/functional/apps/visualize/group5/_tsvb_time_series.ts b/test/functional/apps/visualize/group5/_tsvb_time_series.ts index bbe31dfec6fa0..960932b1314e3 100644 --- a/test/functional/apps/visualize/group5/_tsvb_time_series.ts +++ b/test/functional/apps/visualize/group5/_tsvb_time_series.ts @@ -24,8 +24,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const browser = getService('browser'); const kibanaServer = getService('kibanaServer'); - // Failing: See https://github.com/elastic/kibana/issues/206380 - describe.skip('visual builder', function describeIndexTests() { + describe('visual builder', function describeIndexTests() { before(async () => { await security.testUser.setRoles([ 'kibana_admin', @@ -309,7 +308,12 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(areasCount).to.be(2); expect(legendNames).to.eql(['apache', 'nginx']); - expect(areaColors).to.eql(['#54b399', '#6092c0']); + // We need to use OR condition here because of how visColors are set inconsistently + // See https://github.com/elastic/kibana/issues/206380 + const [firstColor, secondColor] = areaColors!; + expect(['#16c5c0', '#54b399']).contain(firstColor); // first color in elastic palette + expect(['#a6edea', '#6092c0']).contain(secondColor); // second color in elastic palette + expect(areaColors).to.length(2); expect(firstAreaChartData).to.eql(firstAreaExpectedChartData); expect(secondAreaChartData).to.eql(secondAreaExpectedChartData); }); diff --git a/test/functional/services/dashboard/panel_actions.ts b/test/functional/services/dashboard/panel_actions.ts index 31890d4c4c478..aaee40d9199c9 100644 --- a/test/functional/services/dashboard/panel_actions.ts +++ b/test/functional/services/dashboard/panel_actions.ts @@ -19,9 +19,7 @@ const CUSTOMIZE_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-ACTION_CUSTOMIZE_P const OPEN_CONTEXT_MENU_ICON_DATA_TEST_SUBJ = 'embeddablePanelToggleMenuIcon'; const OPEN_INSPECTOR_TEST_SUBJ = 'embeddablePanelAction-openInspector'; const COPY_PANEL_TO_DATA_TEST_SUBJ = 'embeddablePanelAction-copyToDashboard'; -const LEGACY_SAVE_TO_LIBRARY_TEST_SUBJ = 'embeddablePanelAction-legacySaveToLibrary'; const SAVE_TO_LIBRARY_TEST_SUBJ = 'embeddablePanelAction-saveToLibrary'; -const LEGACY_UNLINK_FROM_LIBRARY_TEST_SUBJ = 'embeddablePanelAction-legacyUnlinkFromLibrary'; const UNLINK_FROM_LIBRARY_TEST_SUBJ = 'embeddablePanelAction-unlinkFromLibrary'; const CONVERT_TO_LENS_TEST_SUBJ = 'embeddablePanelAction-ACTION_EDIT_IN_LENS'; @@ -240,13 +238,6 @@ export class DashboardPanelActionsService extends FtrService { return response; } - async legacyUnlinkFromLibrary(title = '') { - this.log.debug(`legacyUnlinkFromLibrary(${title}`); - await this.clickPanelActionByTitle(LEGACY_UNLINK_FROM_LIBRARY_TEST_SUBJ, title); - await this.testSubjects.existOrFail('unlinkPanelSuccess'); - await this.expectNotLinkedToLibrary(title, true); - } - async unlinkFromLibrary(title = '') { this.log.debug(`unlinkFromLibrary(${title})`); await this.clickPanelActionByTitle(UNLINK_FROM_LIBRARY_TEST_SUBJ, title); @@ -254,17 +245,6 @@ export class DashboardPanelActionsService extends FtrService { await this.expectNotLinkedToLibrary(title); } - async legacySaveToLibrary(newTitle = '', oldTitle = '') { - this.log.debug(`legacySaveToLibrary(${newTitle},${oldTitle})`); - await this.clickPanelActionByTitle(LEGACY_SAVE_TO_LIBRARY_TEST_SUBJ, oldTitle); - await this.testSubjects.setValue('savedObjectTitle', newTitle, { - clearWithKeyboard: true, - }); - await this.testSubjects.clickWhenNotDisabledWithoutRetry('confirmSaveSavedObjectButton'); - await this.testSubjects.existOrFail('addPanelToLibrarySuccess'); - await this.expectLinkedToLibrary(newTitle, true); - } - async saveToLibrary(newTitle = '', oldTitle = '') { this.log.debug(`saveToLibraryByTitle(${newTitle},${oldTitle})`); await this.clickPanelActionByTitle(SAVE_TO_LIBRARY_TEST_SUBJ, oldTitle); @@ -413,27 +393,19 @@ export class DashboardPanelActionsService extends FtrService { return await this.convertToLens(wrapper); } - async expectLinkedToLibrary(title = '', legacy?: boolean) { + async expectLinkedToLibrary(title = '') { this.log.debug(`expectLinkedToLibrary(${title})`); const isViewMode = await this.dashboard.getIsInViewMode(); if (isViewMode) await this.dashboard.switchToEditMode(); - if (legacy) { - await this.expectExistsPanelAction(LEGACY_UNLINK_FROM_LIBRARY_TEST_SUBJ, title); - } else { - await this.expectExistsPanelAction(UNLINK_FROM_LIBRARY_TEST_SUBJ, title); - } + await this.expectExistsPanelAction(UNLINK_FROM_LIBRARY_TEST_SUBJ, title); if (isViewMode) await this.dashboard.clickCancelOutOfEditMode(); } - async expectNotLinkedToLibrary(title = '', legacy?: boolean) { + async expectNotLinkedToLibrary(title = '') { this.log.debug(`expectNotLinkedToLibrary(${title})`); const isViewMode = await this.dashboard.getIsInViewMode(); if (isViewMode) await this.dashboard.switchToEditMode(); - if (legacy) { - await this.expectExistsPanelAction(LEGACY_SAVE_TO_LIBRARY_TEST_SUBJ, title); - } else { - await this.expectExistsPanelAction(SAVE_TO_LIBRARY_TEST_SUBJ, title); - } + await this.expectExistsPanelAction(SAVE_TO_LIBRARY_TEST_SUBJ, title); if (isViewMode) await this.dashboard.clickCancelOutOfEditMode(); } } diff --git a/versions.json b/versions.json index 2ba465669fe9a..c7ab2c0e7050c 100644 --- a/versions.json +++ b/versions.json @@ -14,12 +14,12 @@ "previousMinor": true }, { - "version": "8.17.1", + "version": "8.17.2", "branch": "8.17", "previousMajor": true }, { - "version": "8.16.3", + "version": "8.16.4", "branch": "8.16", "previousMajor": true }, diff --git a/x-pack/platform/packages/shared/kbn-cloud-security-posture/common/constants.ts b/x-pack/platform/packages/shared/kbn-cloud-security-posture/common/constants.ts index 9112dba4b9a4f..67b4b5408f742 100644 --- a/x-pack/platform/packages/shared/kbn-cloud-security-posture/common/constants.ts +++ b/x-pack/platform/packages/shared/kbn-cloud-security-posture/common/constants.ts @@ -5,6 +5,7 @@ * 2.0. */ import { VulnSeverity } from './types/vulnerabilities'; +import { MisconfigurationEvaluationStatus } from './types/misconfigurations'; export const KSPM_POLICY_TEMPLATE = 'kspm'; export const CSPM_POLICY_TEMPLATE = 'cspm'; @@ -48,7 +49,8 @@ export const VULNERABILITIES_SEVERITY: Record = { UNKNOWN: 'UNKNOWN', }; -export const MISCONFIGURATION_STATUS: Record = { +export const MISCONFIGURATION_STATUS: Record = { PASSED: 'passed', FAILED: 'failed', + UNKNOWN: 'unknown', }; diff --git a/x-pack/platform/packages/shared/kbn-cloud-security-posture/common/index.ts b/x-pack/platform/packages/shared/kbn-cloud-security-posture/common/index.ts index 4065f7ca331a9..95aad03958940 100644 --- a/x-pack/platform/packages/shared/kbn-cloud-security-posture/common/index.ts +++ b/x-pack/platform/packages/shared/kbn-cloud-security-posture/common/index.ts @@ -24,6 +24,7 @@ export type { } from './schema/vulnerabilities/csp_vulnerability_finding'; export type { BenchmarksCisId } from './types/benchmark'; export type { VulnSeverity } from './types/vulnerabilities'; +export type { MisconfigurationEvaluationStatus } from './types/misconfigurations'; export * from './constants'; export { extractErrorMessage, diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/constants.ts b/x-pack/platform/packages/shared/kbn-cloud-security-posture/common/types/misconfigurations.ts similarity index 58% rename from x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/constants.ts rename to x-pack/platform/packages/shared/kbn-cloud-security-posture/common/types/misconfigurations.ts index 215f0089410e7..bd69554eae7dc 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/constants.ts +++ b/x-pack/platform/packages/shared/kbn-cloud-security-posture/common/types/misconfigurations.ts @@ -5,6 +5,4 @@ * 2.0. */ -export const MAX_CUSTOM_RULES_TO_CREATE_IN_PARALLEL = 50; -export const MAX_PREBUILT_RULES_TO_FETCH = 10_000 as const; -export const MAX_TRANSLATED_RULES_TO_INSTALL = 10_000 as const; +export type MisconfigurationEvaluationStatus = 'passed' | 'failed' | 'unknown'; diff --git a/x-pack/platform/packages/shared/kbn-cloud-security-posture/common/utils/helpers.ts b/x-pack/platform/packages/shared/kbn-cloud-security-posture/common/utils/helpers.ts index 4283436418eab..2984645d1c613 100644 --- a/x-pack/platform/packages/shared/kbn-cloud-security-posture/common/utils/helpers.ts +++ b/x-pack/platform/packages/shared/kbn-cloud-security-posture/common/utils/helpers.ts @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; import type { CspBenchmarkRulesStates } from '../schema/rules/latest'; interface BuildEntityAlertsQueryParams { - field: 'user.name' | 'host.name'; + field: string; to: string; from: string; queryValue?: string; diff --git a/x-pack/platform/packages/shared/kbn-slo-schema/src/schema/slo.ts b/x-pack/platform/packages/shared/kbn-slo-schema/src/schema/slo.ts index c292d355b4867..035d9ed6174fa 100644 --- a/x-pack/platform/packages/shared/kbn-slo-schema/src/schema/slo.ts +++ b/x-pack/platform/packages/shared/kbn-slo-schema/src/schema/slo.ts @@ -77,23 +77,29 @@ function isValidId(id: string): boolean { return validLength && /^[a-z0-9-_]+$/.test(id); } -const sloDefinitionSchema = t.type({ - id: sloIdSchema, - name: t.string, - description: t.string, - indicator: indicatorSchema, - timeWindow: timeWindowSchema, - budgetingMethod: budgetingMethodSchema, - objective: objectiveSchema, - settings: settingsSchema, - revision: t.number, - enabled: t.boolean, - tags: tagsSchema, - createdAt: dateType, - updatedAt: dateType, - groupBy: groupBySchema, - version: t.number, -}); +const sloDefinitionSchema = t.intersection([ + t.type({ + id: sloIdSchema, + name: t.string, + description: t.string, + indicator: indicatorSchema, + timeWindow: timeWindowSchema, + budgetingMethod: budgetingMethodSchema, + objective: objectiveSchema, + settings: settingsSchema, + revision: t.number, + enabled: t.boolean, + tags: tagsSchema, + createdAt: dateType, + updatedAt: dateType, + groupBy: groupBySchema, + version: t.number, + }), + t.partial({ + createdBy: t.string, + updatedBy: t.string, + }), +]); export { budgetingMethodSchema, diff --git a/x-pack/platform/plugins/private/canvas/public/components/datasource/datasource_component.js b/x-pack/platform/plugins/private/canvas/public/components/datasource/datasource_component.js index 0d61015536294..15560ea0010f7 100644 --- a/x-pack/platform/plugins/private/canvas/public/components/datasource/datasource_component.js +++ b/x-pack/platform/plugins/private/canvas/public/components/datasource/datasource_component.js @@ -191,7 +191,6 @@ export class DatasourceComponent extends PureComponent { size="s" onClick={this.save} fill - color="success" data-test-subj="canvasSaveDatasourceButton" > {strings.getSaveButtonLabel()} diff --git a/x-pack/platform/plugins/private/canvas/public/components/page_manager/page_manager.scss b/x-pack/platform/plugins/private/canvas/public/components/page_manager/page_manager.scss index 1f818b980b887..dfff47c61eaa1 100644 --- a/x-pack/platform/plugins/private/canvas/public/components/page_manager/page_manager.scss +++ b/x-pack/platform/plugins/private/canvas/public/components/page_manager/page_manager.scss @@ -33,7 +33,7 @@ .canvasPageManager__addPage { width: $euiSizeXXL + $euiSize; - background: $euiColorSuccess; + background: $euiColorPrimary; color: $euiColorGhost; opacity: 0; animation: buttonPop $euiAnimSpeedNormal $euiAnimSlightResistance; diff --git a/x-pack/platform/plugins/private/canvas/public/components/var_config/edit_var.tsx b/x-pack/platform/plugins/private/canvas/public/components/var_config/edit_var.tsx index 29e026be860a1..30ada32f07c70 100644 --- a/x-pack/platform/plugins/private/canvas/public/components/var_config/edit_var.tsx +++ b/x-pack/platform/plugins/private/canvas/public/components/var_config/edit_var.tsx @@ -209,7 +209,6 @@ export const EditVar: FC = ({ variables, selectedVar, onCancel, onSave }) diff --git a/x-pack/platform/plugins/private/index_lifecycle_management/public/application/sections/edit_policy/components/phase_icon/phase_icon.tsx b/x-pack/platform/plugins/private/index_lifecycle_management/public/application/sections/edit_policy/components/phase_icon/phase_icon.tsx index 7d51b4b07831d..4b965de41eb3c 100644 --- a/x-pack/platform/plugins/private/index_lifecycle_management/public/application/sections/edit_policy/components/phase_icon/phase_icon.tsx +++ b/x-pack/platform/plugins/private/index_lifecycle_management/public/application/sections/edit_policy/components/phase_icon/phase_icon.tsx @@ -7,7 +7,6 @@ import React, { FunctionComponent } from 'react'; import { css } from '@emotion/react'; -import { euiThemeVars } from '@kbn/ui-theme'; import { EuiIcon, useEuiTheme } from '@elastic/eui'; import { Phases } from '../../../../../../common/types'; import './phase_icon.scss'; @@ -21,10 +20,16 @@ export const PhaseIcon: FunctionComponent = ({ enabled, phase }) => { const isBorealis = euiTheme.themeName === 'EUI_THEME_BOREALIS'; const phaseIconColors = { - hot: isBorealis ? euiTheme.colors.vis.euiColorVis6 : euiThemeVars.euiColorVis9_behindText, - warm: isBorealis ? euiTheme.colors.vis.euiColorVis9 : euiThemeVars.euiColorVis5_behindText, - cold: isBorealis ? euiTheme.colors.vis.euiColorVis2 : euiThemeVars.euiColorVis1_behindText, - frozen: euiTheme.colors.vis.euiColorVis4, + hot: isBorealis ? euiTheme.colors.vis.euiColorVis6 : euiTheme.colors.vis.euiColorVisBehindText9, + warm: isBorealis + ? euiTheme.colors.vis.euiColorVis9 + : euiTheme.colors.vis.euiColorVisBehindText5, + cold: isBorealis + ? euiTheme.colors.vis.euiColorVis2 + : euiTheme.colors.vis.euiColorVisBehindText1, + frozen: isBorealis + ? euiTheme.colors.vis.euiColorVis4 + : euiTheme.colors.vis.euiColorVisBehindText4, delete: euiTheme.colors.darkShade, }; diff --git a/x-pack/platform/plugins/private/index_lifecycle_management/tsconfig.json b/x-pack/platform/plugins/private/index_lifecycle_management/tsconfig.json index 00e4ec508cf34..ebd0f7d6e8e2a 100644 --- a/x-pack/platform/plugins/private/index_lifecycle_management/tsconfig.json +++ b/x-pack/platform/plugins/private/index_lifecycle_management/tsconfig.json @@ -40,7 +40,6 @@ "@kbn/unsaved-changes-prompt", "@kbn/shared-ux-table-persist", "@kbn/index-lifecycle-management-common-shared", - "@kbn/ui-theme", ], "exclude": [ "target/**/*", diff --git a/x-pack/platform/plugins/private/snapshot_restore/public/application/components/collapsible_lists/collapsible_indices_list.tsx b/x-pack/platform/plugins/private/snapshot_restore/public/application/components/collapsible_lists/collapsible_indices_list.tsx index 7362a6634565a..8cc29eab33dad 100644 --- a/x-pack/platform/plugins/private/snapshot_restore/public/application/components/collapsible_lists/collapsible_indices_list.tsx +++ b/x-pack/platform/plugins/private/snapshot_restore/public/application/components/collapsible_lists/collapsible_indices_list.tsx @@ -56,7 +56,10 @@ export const CollapsibleIndicesList: React.FunctionComponent = ({ indices values={{ count: hiddenItemsCount }} /> )}{' '} - + ) : null} diff --git a/x-pack/platform/plugins/private/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx b/x-pack/platform/plugins/private/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx index 6ad3e1704720f..4ebf98bf00efb 100644 --- a/x-pack/platform/plugins/private/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx +++ b/x-pack/platform/plugins/private/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx @@ -211,6 +211,7 @@ export const IndicesAndDataStreamsField: FunctionComponent = ({ setSelectIndicesMode('custom'); onUpdate({ indices: indexPatterns.join(',') }); }} + data-test-subj="useIndexPatternsButton" > = }); } }} + data-test-subj="allDsAndIndicesToggle" /> {isAllIndicesAndDataStreams ? null : ( @@ -281,6 +282,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = setSelectIndicesMode('custom'); updateRestoreSettings({ indices: restoreIndexPatterns.join(',') }); }} + data-test-subj="restoreIndexPatternsButton" > = }); } }} + data-test-subj="restoreRenameToggle" /> {!isRenamingIndices ? null : ( @@ -510,6 +513,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = renamePattern: e.target.value, }); }} + data-test-subj="capturePattern" /> @@ -536,6 +540,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = renameReplacement: e.target.value, }); }} + data-test-subj="replacementPattern" /> diff --git a/x-pack/platform/plugins/private/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_review.tsx b/x-pack/platform/plugins/private/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_review.tsx index 09feaf61ca9e7..b3e3879e332b5 100644 --- a/x-pack/platform/plugins/private/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_review.tsx +++ b/x-pack/platform/plugins/private/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_review.tsx @@ -301,7 +301,7 @@ export const RestoreSnapshotStepReview: React.FunctionComponent = ({ return ( - +

= ( {/* Step title and doc link */} - +

= ({ ); }, disabled: Boolean(policyDetails.policy.inProgress), + 'data-test-subj': 'policyActionMenuRunPolicy', }, { name: i18n.translate( diff --git a/x-pack/platform/plugins/private/snapshot_restore/public/application/sections/home/restore_list/restore_table/restore_table.tsx b/x-pack/platform/plugins/private/snapshot_restore/public/application/sections/home/restore_list/restore_table/restore_table.tsx index ff5f904770aa1..ee7d6f9c4be2a 100644 --- a/x-pack/platform/plugins/private/snapshot_restore/public/application/sections/home/restore_list/restore_table/restore_table.tsx +++ b/x-pack/platform/plugins/private/snapshot_restore/public/application/sections/home/restore_list/restore_table/restore_table.tsx @@ -107,6 +107,7 @@ export const RestoreTable: React.FunctionComponent = React.memo(({ restor }), truncateText: true, sortable: true, + 'data-test-subj': 'restoreTableIndex', }, { field: 'isComplete', @@ -115,6 +116,7 @@ export const RestoreTable: React.FunctionComponent = React.memo(({ restor }), truncateText: true, sortable: true, + 'data-test-subj': 'restoreTableIsComplete', render: (isComplete: SnapshotRestore['isComplete']) => isComplete ? ( diff --git a/x-pack/platform/plugins/private/snapshot_restore/public/application/sections/home/snapshot_list/components/snapshot_table.tsx b/x-pack/platform/plugins/private/snapshot_restore/public/application/sections/home/snapshot_list/components/snapshot_table.tsx index e4907709f7e1e..082c0775b6dfc 100644 --- a/x-pack/platform/plugins/private/snapshot_restore/public/application/sections/home/snapshot_list/components/snapshot_table.tsx +++ b/x-pack/platform/plugins/private/snapshot_restore/public/application/sections/home/snapshot_list/components/snapshot_table.tsx @@ -99,6 +99,7 @@ export const SnapshotTable: React.FunctionComponent = (props: Props) => { name: i18n.translate('xpack.snapshotRestore.snapshotList.table.stateColumnTitle', { defaultMessage: 'State', }), + 'data-test-subj': 'snapshotState', truncateText: false, sortable: false, render: (state: string) => , diff --git a/x-pack/platform/plugins/private/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_details/snapshot_details.tsx b/x-pack/platform/plugins/private/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_details/snapshot_details.tsx index b3c510e0fa0c7..db4efbbf80965 100644 --- a/x-pack/platform/plugins/private/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_details/snapshot_details.tsx +++ b/x-pack/platform/plugins/private/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_details/snapshot_details.tsx @@ -233,6 +233,7 @@ export const SnapshotDetails: React.FunctionComponent = ({ snapshotDetails.state !== SNAPSHOT_STATE.SUCCESS && snapshotDetails.state !== SNAPSHOT_STATE.PARTIAL } + data-test-subj="restoreSnapshotButton" > } error={saveError} + data-test-subj="restoreSnapshotError" /> ) : null; }; diff --git a/x-pack/platform/plugins/private/translations/translations/fr-FR.json b/x-pack/platform/plugins/private/translations/translations/fr-FR.json index 0fb274620e0fc..3893fdc0986fc 100644 --- a/x-pack/platform/plugins/private/translations/translations/fr-FR.json +++ b/x-pack/platform/plugins/private/translations/translations/fr-FR.json @@ -2766,8 +2766,6 @@ "embeddableApi.multiValueClickTrigger.title": "Clics multiples", "embeddableApi.panelBadgeTrigger.description": "Des actions apparaissent dans la barre de titre lorsqu'un élément pouvant être intégré est chargé dans un panneau.", "embeddableApi.panelBadgeTrigger.title": "Badges du panneau", - "embeddableApi.panelHoverTrigger.description": "Une nouvelle action sera ajoutée au menu flottant du panneau", - "embeddableApi.panelHoverTrigger.title": "Menu contextuel du panneau", "embeddableApi.panelNotificationTrigger.description": "Les actions apparaissent dans l’angle supérieur droit des panneaux.", "embeddableApi.panelNotificationTrigger.title": "Notifications du panneau", "embeddableApi.reactEmbeddable.factoryAlreadyExistsError": "Une usine incorporable pour le type : {key} est déjà enregistrée.", @@ -4734,15 +4732,10 @@ "indexPatternFieldEditor.cancelField.confirmationModal.cancelButtonLabel": "Annuler", "indexPatternFieldEditor.cancelField.confirmationModal.description": "Les modifications apportées à votre champ seront ignorées. Voulez-vous vraiment continuer ?", "indexPatternFieldEditor.cancelField.confirmationModal.title": "Ignorer les modifications", - "indexPatternFieldEditor.color.actions": "Actions", "indexPatternFieldEditor.color.addColorButton": "Ajouter une couleur", - "indexPatternFieldEditor.color.backgroundLabel": "Couleur d'arrière-plan", - "indexPatternFieldEditor.color.deleteAria": "Supprimer", "indexPatternFieldEditor.color.deleteTitle": "Supprimer le format de couleur", - "indexPatternFieldEditor.color.exampleLabel": "Exemple", - "indexPatternFieldEditor.color.patternLabel": "Modèle (expression régulière)", - "indexPatternFieldEditor.color.rangeLabel": "Plage (min:max)", - "indexPatternFieldEditor.color.textColorLabel": "Couleur du texte", + "indexPatternFieldEditor.color.patternLabel": "Modèle", + "indexPatternFieldEditor.color.rangeLabel": "Plage", "indexPatternFieldEditor.createField.flyoutAriaLabel": "Créer un champ", "indexPatternFieldEditor.date.documentationLabel": "Documentation", "indexPatternFieldEditor.date.momentLabel": "Modèle de format Moment.js (par défaut : {defaultPattern})", @@ -6221,8 +6214,6 @@ "presentationPanel.filters.filtersTitle": "Filtres", "presentationPanel.filters.queryTitle": "Recherche", "presentationPanel.header.titleAriaLabel": "Cliquez pour modifier le titre : {title}", - "presentationPanel.hoverTrigger.description": "Une nouvelle action sera ajoutée au menu flottant du panneau", - "presentationPanel.hoverTrigger.title": "Menu contextuel du panneau", "presentationPanel.notificationTrigger.description": "Les actions de notification apparaissent dans l'angle supérieur droit des panneaux.", "presentationPanel.notificationTrigger.title": "Notifications du panneau", "presentationPanel.placeholderTitle": "[Aucun titre]", @@ -17564,7 +17555,6 @@ "xpack.enterpriseSearch.searchNav.otherTools": "Autres outils", "xpack.enterpriseSearch.searchNav.relevance": "Pertinence", "xpack.enterpriseSearch.searchProvider.aiSearch.name": "Intelligence artificielle de recherche", - "xpack.enterpriseSearch.searchProvider.webCrawler.name": "Robot d'indexation d'Elastic", "xpack.enterpriseSearch.selectConnector.badgeOnClick.ariaLabel": "Cliquer pour ouvrir la fenêtre contextuelle d'explication du connecteur", "xpack.enterpriseSearch.selectConnector.connectorClientBadgeLabel": "Autogéré", "xpack.enterpriseSearch.selectConnector.h4.connectorClientsLabel": "Connecteurs autogérés", @@ -36637,7 +36627,6 @@ "xpack.securitySolution.detectionEngine.ruleDetails.enableRuleLabel": "Activer", "xpack.securitySolution.detectionEngine.ruleDetails.endpointExceptionsTab": "Exceptions de point de terminaison", "xpack.securitySolution.detectionEngine.ruleDetails.falsePositivesFieldLabel": "Exemples de faux positifs", - "xpack.securitySolution.detectionEngine.ruleDetails.fromFieldLabel": "Temps de récupération supplémentaire", "xpack.securitySolution.detectionEngine.ruleDetails.historyWindowSizeFieldLabel": "Taille de la fenêtre d’historique", "xpack.securitySolution.detectionEngine.ruleDetails.indexFieldLabel": "Modèles d'indexation", "xpack.securitySolution.detectionEngine.ruleDetails.installAndEnableButtonLabel": "Installer et activer", @@ -40087,7 +40076,6 @@ "xpack.securitySolution.system.withResultDescription": "avec le résultat", "xpack.securitySolution.tables.rowItemHelper.moreDescription": "plus non affiché", "xpack.securitySolution.tables.rowItemHelper.overflowButtonDescription": "+ {count} de plus", - "xpack.securitySolution.threatIntelligence.investigateInTimelineTitle": "Investiguer dans la chronologie", "xpack.securitySolution.threatMatch.andDescription": "AND", "xpack.securitySolution.threatMatch.fieldDescription": "Champ", "xpack.securitySolution.threatMatch.fieldPlaceholderDescription": "Rechercher", @@ -41104,7 +41092,6 @@ "xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel": "{numOfSlos, number} {numOfSlos, plural, other {SLO}} inclus", "xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel.instancesCount": "({count, number} {count, plural, one {Instance} other {Instances}})", "xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel.withInstances": "{numOfSlos, number} {numOfSlos, plural, other {SLO}}{instances} inclus", - "xpack.slo.sloCardItem.euiPanel.lastUpdatedLabel": "{status}, dernière mise à jour : {value}", "xpack.slo.sloCardItemBadges.remoteBadgeLabel": "Distant", "xpack.slo.sloConfiguration.euiSwitch.showAllGroupByLabel": "Afficher toutes les instances de regroupement associées ", "xpack.slo.sloCreatePageTitle": "Créer un nouveau SLO", @@ -41128,8 +41115,6 @@ "xpack.slo.sloDetails.headerControl.manageRules": "Gérer {count, plural, one {règle} other {règles}} du taux d'avancement", "xpack.slo.sloDetails.headerTitle.calloutDescription": "Il s'agit d'un SLO distant qui appartient à une autre instance Kibana. Il est extrait du cluster distant : {remoteName} avec l'URL Kibana {kibanaUrl}.", "xpack.slo.sloDetails.headerTitle.calloutMessage": "SLO distant", - "xpack.slo.sloDetails.headerTitle.createdMessage": "Créé le", - "xpack.slo.sloDetails.headerTitle.lastUpdatedMessage": "Dernière mise à jour le", "xpack.slo.sloDetails.healthCallout.buttonTransformLabel": "Inspecter la transformation", "xpack.slo.sloDetails.healthCallout.copyToClipboard": "Copier dans le presse-papiers", "xpack.slo.sloDetails.healthCallout.description": "{count, plural, one {La transformation suivante est} other {Les transformations suivantes sont} } dans un état défectueux :", diff --git a/x-pack/platform/plugins/private/translations/translations/ja-JP.json b/x-pack/platform/plugins/private/translations/translations/ja-JP.json index 32130dd35e7ed..bf5f929868d4c 100644 --- a/x-pack/platform/plugins/private/translations/translations/ja-JP.json +++ b/x-pack/platform/plugins/private/translations/translations/ja-JP.json @@ -2761,8 +2761,6 @@ "embeddableApi.multiValueClickTrigger.title": "マルチクリック", "embeddableApi.panelBadgeTrigger.description": "パネルに埋め込み可能なファイルが読み込まれるときに、アクションがタイトルバーに表示されます。", "embeddableApi.panelBadgeTrigger.title": "パネルバッジ", - "embeddableApi.panelHoverTrigger.description": "新しいアクションがパネルのマウスオーバーメニューに追加されます", - "embeddableApi.panelHoverTrigger.title": "パネルマウスオーバー", "embeddableApi.panelNotificationTrigger.description": "パネルの右上にアクションが表示されます。", "embeddableApi.panelNotificationTrigger.title": "パネル通知", "embeddableApi.reactEmbeddable.factoryAlreadyExistsError": "タイプ\"{key}\"の埋め込み可能ファクトリはすでに登録されています。", @@ -4729,15 +4727,10 @@ "indexPatternFieldEditor.cancelField.confirmationModal.cancelButtonLabel": "キャンセル", "indexPatternFieldEditor.cancelField.confirmationModal.description": "フィールドの変更は破棄されます。続行しますか?", "indexPatternFieldEditor.cancelField.confirmationModal.title": "変更を破棄", - "indexPatternFieldEditor.color.actions": "アクション", "indexPatternFieldEditor.color.addColorButton": "色を追加", - "indexPatternFieldEditor.color.backgroundLabel": "背景色", - "indexPatternFieldEditor.color.deleteAria": "削除", "indexPatternFieldEditor.color.deleteTitle": "色のフォーマットを削除", - "indexPatternFieldEditor.color.exampleLabel": "例", - "indexPatternFieldEditor.color.patternLabel": "パターン(正規表現)", - "indexPatternFieldEditor.color.rangeLabel": "範囲(min:max)", - "indexPatternFieldEditor.color.textColorLabel": "文字の色", + "indexPatternFieldEditor.color.patternLabel": "パターン", + "indexPatternFieldEditor.color.rangeLabel": "範囲", "indexPatternFieldEditor.createField.flyoutAriaLabel": "フィールドを作成", "indexPatternFieldEditor.date.documentationLabel": "ドキュメント", "indexPatternFieldEditor.date.momentLabel": "Moment.jsのフォーマットパターン(デフォルト:{defaultPattern})", @@ -6215,8 +6208,6 @@ "presentationPanel.filters.filtersTitle": "フィルター", "presentationPanel.filters.queryTitle": "クエリー", "presentationPanel.header.titleAriaLabel": "クリックしてタイトルを編集:{title}", - "presentationPanel.hoverTrigger.description": "新しいアクションがパネルのマウスオーバーメニューに追加されます", - "presentationPanel.hoverTrigger.title": "パネルマウスオーバー", "presentationPanel.notificationTrigger.description": "パネルの右上に通知アクションが表示されます。", "presentationPanel.notificationTrigger.title": "パネル通知", "presentationPanel.placeholderTitle": "[タイトルなし]", @@ -17422,7 +17413,6 @@ "xpack.enterpriseSearch.searchNav.mngt": "スタック管理", "xpack.enterpriseSearch.searchNav.otherTools": "その他のツール", "xpack.enterpriseSearch.searchProvider.aiSearch.name": "検索AI", - "xpack.enterpriseSearch.searchProvider.webCrawler.name": "Elastic Webクローラー", "xpack.enterpriseSearch.selectConnector.badgeOnClick.ariaLabel": "クリックすると、コネクター説明ポップオーバーが開きます", "xpack.enterpriseSearch.selectConnector.connectorClientBadgeLabel": "セルフマネージド", "xpack.enterpriseSearch.selectConnector.h4.connectorClientsLabel": "セルフマネージドコネクター", @@ -36496,7 +36486,6 @@ "xpack.securitySolution.detectionEngine.ruleDetails.enableRuleLabel": "有効にする", "xpack.securitySolution.detectionEngine.ruleDetails.endpointExceptionsTab": "エンドポイント例外", "xpack.securitySolution.detectionEngine.ruleDetails.falsePositivesFieldLabel": "誤検出の例", - "xpack.securitySolution.detectionEngine.ruleDetails.fromFieldLabel": "追加のルックバック時間", "xpack.securitySolution.detectionEngine.ruleDetails.historyWindowSizeFieldLabel": "履歴ウィンドウサイズ", "xpack.securitySolution.detectionEngine.ruleDetails.indexFieldLabel": "インデックスパターン", "xpack.securitySolution.detectionEngine.ruleDetails.installAndEnableButtonLabel": "インストールして有効化", @@ -39947,7 +39936,6 @@ "xpack.securitySolution.system.withResultDescription": "結果付き", "xpack.securitySolution.tables.rowItemHelper.moreDescription": "行は表示されていません", "xpack.securitySolution.tables.rowItemHelper.overflowButtonDescription": "他{count}件", - "xpack.securitySolution.threatIntelligence.investigateInTimelineTitle": "タイムラインで調査", "xpack.securitySolution.threatMatch.andDescription": "AND", "xpack.securitySolution.threatMatch.fieldDescription": "フィールド", "xpack.securitySolution.threatMatch.fieldPlaceholderDescription": "検索", @@ -40961,7 +40949,6 @@ "xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel": "{numOfSlos, number} {numOfSlos, plural, other {SLO}}が含まれます", "xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel.instancesCount": "({count, number} {count, plural, other {インスタンス}})", "xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel.withInstances": "{numOfSlos, number} {numOfSlos, plural, other {SLO}}{instances}が含まれます", - "xpack.slo.sloCardItem.euiPanel.lastUpdatedLabel": "{status}、前回更新日:{value}", "xpack.slo.sloCardItemBadges.remoteBadgeLabel": "リモート", "xpack.slo.sloConfiguration.euiSwitch.showAllGroupByLabel": "インスタンス別にすべての関連するグループを表示", "xpack.slo.sloCreatePageTitle": "新規SLOを作成", @@ -40985,8 +40972,6 @@ "xpack.slo.sloDetails.headerControl.manageRules": "バーンレート{count, plural, other {ルール}}を管理", "xpack.slo.sloDetails.headerTitle.calloutDescription": "これは別のKibanaインスタンスに属するリモートSLOです。リモートクラスターから取得されます:Kibana URL {kibanaUrl}の{remoteName}。", "xpack.slo.sloDetails.headerTitle.calloutMessage": "リモートSLO", - "xpack.slo.sloDetails.headerTitle.createdMessage": "作成日時", - "xpack.slo.sloDetails.headerTitle.lastUpdatedMessage": "最終更新日", "xpack.slo.sloDetails.healthCallout.buttonTransformLabel": "変換を検査", "xpack.slo.sloDetails.healthCallout.copyToClipboard": "クリップボードにコピー", "xpack.slo.sloDetails.healthCallout.description": "次の{count, plural, other {変換は} }正常ではない状態です。", diff --git a/x-pack/platform/plugins/private/translations/translations/zh-CN.json b/x-pack/platform/plugins/private/translations/translations/zh-CN.json index f292e3a323fcc..df957cdd32c69 100644 --- a/x-pack/platform/plugins/private/translations/translations/zh-CN.json +++ b/x-pack/platform/plugins/private/translations/translations/zh-CN.json @@ -2755,8 +2755,6 @@ "embeddableApi.multiValueClickTrigger.title": "多次单击", "embeddableApi.panelBadgeTrigger.description": "可嵌入对象在面板加载后,操作便显示在标题栏中。", "embeddableApi.panelBadgeTrigger.title": "面板徽章", - "embeddableApi.panelHoverTrigger.description": "会将一个新操作添加到该面板的悬停菜单", - "embeddableApi.panelHoverTrigger.title": "面板悬停", "embeddableApi.panelNotificationTrigger.description": "操作显示在面板右上角。", "embeddableApi.panelNotificationTrigger.title": "面板通知", "embeddableApi.reactEmbeddable.factoryAlreadyExistsError": "已注册类型为 {key} 的可嵌入工厂。", @@ -4709,15 +4707,10 @@ "indexPatternFieldEditor.cancelField.confirmationModal.cancelButtonLabel": "取消", "indexPatternFieldEditor.cancelField.confirmationModal.description": "将会丢弃对您的字段所做的更改,是否确定要继续?", "indexPatternFieldEditor.cancelField.confirmationModal.title": "放弃更改", - "indexPatternFieldEditor.color.actions": "操作", "indexPatternFieldEditor.color.addColorButton": "添加颜色", - "indexPatternFieldEditor.color.backgroundLabel": "背景色", - "indexPatternFieldEditor.color.deleteAria": "删除", "indexPatternFieldEditor.color.deleteTitle": "删除颜色格式", - "indexPatternFieldEditor.color.exampleLabel": "示例", - "indexPatternFieldEditor.color.patternLabel": "模式(正则表达式)", - "indexPatternFieldEditor.color.rangeLabel": "范围(最小值:最大值)", - "indexPatternFieldEditor.color.textColorLabel": "文本颜色", + "indexPatternFieldEditor.color.patternLabel": "模式", + "indexPatternFieldEditor.color.rangeLabel": "范围", "indexPatternFieldEditor.createField.flyoutAriaLabel": "创建字段", "indexPatternFieldEditor.date.documentationLabel": "文档", "indexPatternFieldEditor.date.momentLabel": "Moment.js 格式模式(默认值:{defaultPattern})", @@ -6172,8 +6165,6 @@ "presentationPanel.filters.filtersTitle": "筛选", "presentationPanel.filters.queryTitle": "查询", "presentationPanel.header.titleAriaLabel": "单击可编辑标题:{title}", - "presentationPanel.hoverTrigger.description": "会将一个新操作添加到该面板的悬停菜单", - "presentationPanel.hoverTrigger.title": "面板悬停", "presentationPanel.notificationTrigger.description": "通知操作显示在面板右上角。", "presentationPanel.notificationTrigger.title": "面板通知", "presentationPanel.placeholderTitle": "[无标题]", @@ -17143,7 +17134,6 @@ "xpack.enterpriseSearch.searchNav.otherTools": "其他工具", "xpack.enterpriseSearch.searchNav.relevance": "相关性", "xpack.enterpriseSearch.searchProvider.aiSearch.name": "搜索 AI", - "xpack.enterpriseSearch.searchProvider.webCrawler.name": "Elastic 网络爬虫", "xpack.enterpriseSearch.selectConnector.badgeOnClick.ariaLabel": "单击以打开连接器说明弹出框", "xpack.enterpriseSearch.selectConnector.connectorClientBadgeLabel": "自管型", "xpack.enterpriseSearch.selectConnector.h4.connectorClientsLabel": "自管型连接器", @@ -35954,7 +35944,6 @@ "xpack.securitySolution.detectionEngine.ruleDetails.enableRuleLabel": "启用", "xpack.securitySolution.detectionEngine.ruleDetails.endpointExceptionsTab": "终端例外", "xpack.securitySolution.detectionEngine.ruleDetails.falsePositivesFieldLabel": "误报示例", - "xpack.securitySolution.detectionEngine.ruleDetails.fromFieldLabel": "更多回查时间", "xpack.securitySolution.detectionEngine.ruleDetails.historyWindowSizeFieldLabel": "历史记录窗口大小", "xpack.securitySolution.detectionEngine.ruleDetails.indexFieldLabel": "索引模式", "xpack.securitySolution.detectionEngine.ruleDetails.installAndEnableButtonLabel": "安装并启用", @@ -39366,7 +39355,6 @@ "xpack.securitySolution.system.withResultDescription": ",结果为", "xpack.securitySolution.tables.rowItemHelper.moreDescription": "未显示", "xpack.securitySolution.tables.rowItemHelper.overflowButtonDescription": "另外 {count} 个", - "xpack.securitySolution.threatIntelligence.investigateInTimelineTitle": "在时间线中调查", "xpack.securitySolution.threatMatch.andDescription": "且", "xpack.securitySolution.threatMatch.fieldDescription": "字段", "xpack.securitySolution.threatMatch.fieldPlaceholderDescription": "搜索", @@ -40375,7 +40363,6 @@ "xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel": "已包括 {numOfSlos, number} 个 {numOfSlos, plural, other {SLO}}", "xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel.instancesCount": "({count, number} 个{count, plural, other {实例}})", "xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel.withInstances": "已包括 {numOfSlos, number} 个 {numOfSlos, plural, other {SLO}}{instances}", - "xpack.slo.sloCardItem.euiPanel.lastUpdatedLabel": "{status},上次更新时间:{value}", "xpack.slo.sloCardItemBadges.remoteBadgeLabel": "远程", "xpack.slo.sloConfiguration.euiSwitch.showAllGroupByLabel": "显示所有相关分组依据实例", "xpack.slo.sloCreatePageTitle": "创建新 SLO", @@ -40399,8 +40386,6 @@ "xpack.slo.sloDetails.headerControl.manageRules": "管理消耗速度{count, plural, other {规则}}", "xpack.slo.sloDetails.headerTitle.calloutDescription": "这是一个远程 SLO,它属于其他 Kibana 实例。它是使用 Kibana URL {kibanaUrl} 从远程集群 {remoteName} 提取的。", "xpack.slo.sloDetails.headerTitle.calloutMessage": "远程 SLO", - "xpack.slo.sloDetails.headerTitle.createdMessage": "创建日期", - "xpack.slo.sloDetails.headerTitle.lastUpdatedMessage": "上次更新时间", "xpack.slo.sloDetails.healthCallout.buttonTransformLabel": "检查转换", "xpack.slo.sloDetails.healthCallout.copyToClipboard": "复制到剪贴板", "xpack.slo.sloDetails.healthCallout.description": "以下{count, plural, other {转换}}处于运行不正常状态:", diff --git a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/reindexing/index_settings.test.ts b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/reindexing/index_settings.test.ts index 685bc443c324c..17eadc16c6229 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/reindexing/index_settings.test.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/reindexing/index_settings.test.ts @@ -8,124 +8,11 @@ import { versionService } from '../version'; import { getMockVersionInfo } from '../__fixtures__/version'; -import { - generateNewIndexName, - getReindexWarnings, - sourceNameForIndex, - transformFlatSettings, -} from './index_settings'; +import { generateNewIndexName, getReindexWarnings, sourceNameForIndex } from './index_settings'; const { currentMajor, prevMajor } = getMockVersionInfo(); -describe('transformFlatSettings', () => { - it('does not blow up for empty mappings', () => { - expect( - transformFlatSettings({ - settings: {}, - mappings: {}, - }) - ).toEqual({ - settings: {}, - mappings: {}, - }); - }); - - it('removes settings that cannot be set on a new index', () => { - expect( - transformFlatSettings({ - settings: { - // Settings that should get preserved - 'index.number_of_replicas': '1', - 'index.number_of_shards': '5', - - // Blacklisted settings - 'index.allocation.existing_shards_allocator': 'gateway_allocator', - 'index.blocks.write': 'true', - 'index.creation_date': '1547052614626', - 'index.frozen': 'true', - 'index.history.uuid': 'i66b9149a-00ee-42d9-8ca1-85ae9279234gh', - 'index.merge.enabled': 'true', - 'index.provided_name': 'test1', - 'index.resize.source.name': 'resizeName', - 'index.resize.source.uuid': 'k34b9149a-00ee-42d9-8ca1-85ae9279234zs', - 'index.routing.allocation.initial_recovery._id': '1', - 'index.search.throttled': 'true', - 'index.source_only': 'true', - 'index.shrink.source.name': 'shrinkSourceName', - 'index.shrink.source.uuid': 'q34b9149a-00ee-42d9-8ca1-85ae234324df', - 'index.store.snapshot.repository_name': 'repoName', - 'index.store.snapshot.snapshot_name': 'snapshotName', - 'index.store.snapshot.snapshot_uuid': 'f345c9149a-00ee-42d9-8ca1-85ae234324df', - 'index.store.snapshot.index_name': 'snapshotIndexName', - 'index.store.snapshot.index_uuid': 'h764f9149a-00ee-42d9-8ca1-85ae234324af', - 'index.uuid': 'i66b9149a-00ee-42d9-8ca1-85ae927924bf', - 'index.verified_before_close': 'true', - 'index.version.created': '123123', - 'index.version.upgraded': '123123', - 'index.mapper.dynamic': 'true', - - // Deprecated settings - 'index.force_memory_term_dictionary': '1024', - 'index.max_adjacency_matrix_filters': 'true', - 'index.soft_deletes.enabled': 'true', - }, - mappings: {}, - }) - ).toEqual({ - settings: { - 'index.number_of_replicas': '1', - 'index.number_of_shards': '5', - }, - mappings: {}, - }); - }); - - it('removes index.translog.retention.size if soft deletes is enabled', () => { - expect( - transformFlatSettings({ - settings: { - // Settings that should get preserved - 'index.number_of_replicas': '1', - 'index.number_of_shards': '5', - - // Deprecated settings - 'index.soft_deletes.enabled': 'true', - 'index.translog.retention.size': '5b', - }, - mappings: {}, - }) - ).toEqual({ - settings: { - 'index.number_of_replicas': '1', - 'index.number_of_shards': '5', - }, - mappings: {}, - }); - }); - - it('removes index.translog.retention.age if soft deletes is enabled', () => { - expect( - transformFlatSettings({ - settings: { - // Settings that should get preserved - 'index.number_of_replicas': '1', - 'index.number_of_shards': '5', - - // Deprecated settings - 'index.soft_deletes.enabled': 'true', - 'index.translog.retention.age': '5d', - }, - mappings: {}, - }) - ).toEqual({ - settings: { - 'index.number_of_replicas': '1', - 'index.number_of_shards': '5', - }, - mappings: {}, - }); - }); - +describe('index settings', () => { describe('sourceNameForIndex', () => { beforeEach(() => { versionService.setup('8.0.0'); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/reindexing/index_settings.ts b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/reindexing/index_settings.ts index 3344ecde4ab69..178df91be6096 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/reindexing/index_settings.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/reindexing/index_settings.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { flow, omit } from 'lodash'; import { ReindexWarning } from '../../../common/types'; import { versionService } from '../version'; import { FlatSettings } from './types'; @@ -27,17 +26,6 @@ const deprecatedSettings = [ 'index.soft_deletes.enabled', ]; -/** - * Validates, and updates deprecated settings and mappings to be applied to the - * new updated index. - */ -export const transformFlatSettings = (flatSettings: FlatSettings) => { - const settings = transformSettings(flatSettings.settings); - const mappings = transformMappings(flatSettings.mappings); - - return { settings, mappings }; -}; - /** * Provides the assumed source of the index name stripping any prefixing * introduced by the upgrade assistant @@ -125,63 +113,3 @@ export const getReindexWarnings = (flatSettings: FlatSettings): ReindexWarning[] return warnings; }; - -const removeUnsettableSettings = (settings: FlatSettings['settings']) => - omit(settings, [ - // Private ES settings - 'index.allocation.existing_shards_allocator', - 'index.blocks.write', - 'index.creation_date', - 'index.frozen', - 'index.history.uuid', - 'index.merge.enabled', - 'index.provided_name', - 'index.resize.source.name', - 'index.resize.source.uuid', - 'index.routing.allocation.initial_recovery._id', - 'index.search.throttled', - 'index.source_only', - 'index.shrink.source.name', - 'index.shrink.source.uuid', - 'index.store.snapshot.repository_name', - 'index.store.snapshot.snapshot_name', - 'index.store.snapshot.snapshot_uuid', - 'index.store.snapshot.index_name', - 'index.store.snapshot.index_uuid', - 'index.uuid', - 'index.verified_before_close', - 'index.version.created', - - // Ignored since 6.x and forbidden in 7.x - 'index.mapper.dynamic', - - // Deprecated in 9.0 - 'index.version.upgraded', - ]); - -const removeDeprecatedSettings = (settings: FlatSettings['settings']) => { - const updatedSettings = { ...settings }; - - // Translog settings are only marked as deprecated if soft deletes is enabled - if (updatedSettings['index.soft_deletes.enabled'] === 'true') { - if (updatedSettings['index.translog.retention.size']) { - delete updatedSettings['index.translog.retention.size']; - } - - // @ts-expect-error @elastic/elasticsearch doesn't declare such a setting - if (settings['index.translog.retention.age']) { - delete updatedSettings['index.translog.retention.age']; - } - } - - return omit(updatedSettings, deprecatedSettings); -}; - -// Use `flow` to pipe the settings through each function. -const transformSettings = flow(removeUnsettableSettings, removeDeprecatedSettings); - -const updateFixableMappings = (mappings: FlatSettings['mappings']) => { - return mappings; -}; - -const transformMappings = flow(updateFixableMappings); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts index e5c2b6beb4a6f..cef50f37b2994 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts @@ -457,19 +457,21 @@ describe('reindexService', () => { // The more intricate details of how the settings are chosen are test separately. it('creates new index with settings and mappings and updates lastCompletedStep', async () => { actions.getFlatSettings.mockResolvedValueOnce(settingsMappings); - clusterClient.asCurrentUser.indices.create.mockResponse( - // @ts-expect-error not full interface - { acknowledged: true } - ); + clusterClient.asCurrentUser.transport.request.mockResolvedValueOnce({ acknowledged: true }); const updatedOp = await service.processNextStep(reindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.newIndexCreated); - expect(clusterClient.asCurrentUser.indices.create).toHaveBeenCalledWith({ - index: 'myIndex-reindex-0', - // index.blocks.write should be removed from the settings for the new index. - // index.number_of_replicas and index.refresh_interval are stored to be set at a later stage. - // Setting to 0 and -1, respectively, right now. - settings: { 'index.number_of_replicas': 0, 'index.refresh_interval': -1 }, - mappings: settingsMappings.mappings, + expect(clusterClient.asCurrentUser.transport.request).toHaveBeenCalledWith({ + method: 'POST', + path: `_create_from/myIndex/myIndex-reindex-0`, + body: { + settings_override: { + 'index.blocks.read_only': null, + 'index.blocks.read_only_allow_delete': null, + 'index.blocks.write': null, + 'index.number_of_replicas': 0, + 'index.refresh_interval': -1, + }, + }, }); }); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/reindexing/reindex_service.ts b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/reindexing/reindex_service.ts index f26a9b72252a5..a6f85e45e3676 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/reindexing/reindex_service.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/reindexing/reindex_service.ts @@ -19,12 +19,7 @@ import { import { esIndicesStateCheck } from '../es_indices_state_check'; -import { - generateNewIndexName, - getReindexWarnings, - sourceNameForIndex, - transformFlatSettings, -} from './index_settings'; +import { generateNewIndexName, getReindexWarnings, sourceNameForIndex } from './index_settings'; import { ReindexActions } from './reindex_actions'; @@ -190,7 +185,7 @@ export const reindexServiceFactory = ( throw error.indexNotFound(`Index ${indexName} does not exist.`); } - const { settings, mappings } = transformFlatSettings(flatSettings); + const { settings = {} } = flatSettings; // Backup the current settings to restore them after the reindex // https://github.com/elastic/kibana/issues/201605 @@ -201,16 +196,31 @@ export const reindexServiceFactory = ( let createIndex; try { - createIndex = await esClient.indices.create({ - index: newIndexName, - settings: { - ...settings, - // Reindexing optimizations - 'index.number_of_replicas': 0, - 'index.refresh_interval': -1, + createIndex = await esClient.transport.request<{ acknowledged: boolean }>({ + method: 'POST', + path: `_create_from/${indexName}/${newIndexName}`, + body: { + // Settings overrides copied from ES datastream reindex logic + // https://github.com/elastic/elasticsearch/blob/9c0709f386fee4154e930cb61a02868adebe8572/x-pack/plugin/migrate/src/main/java/org/elasticsearch/xpack/migrate/action/ReindexDataStreamIndexTransportAction.java#L195-L210 + settings_override: { + // Remove read-only settings if they exist + 'index.blocks.read_only': null, + 'index.blocks.read_only_allow_delete': null, + 'index.blocks.write': null, + // Reindexing optimizations + 'index.number_of_replicas': 0, + 'index.refresh_interval': -1, + }, }, - mappings, }); + /** + * Response is expected to be: + * { + * "acknowledged": true, + * "shards_acknowledged": true, + * "index": "test-copy" + * } + */ } catch (err) { // If for any reason the new index name generated by the `generateNewIndexName` already // exists (this could happen if kibana is restarted during reindexing), we can just go diff --git a/x-pack/platform/plugins/shared/actions/server/application/connector/methods/get_all/get_all.ts b/x-pack/platform/plugins/shared/actions/server/application/connector/methods/get_all/get_all.ts index caa5a361ae454..15aa19452a6f9 100644 --- a/x-pack/platform/plugins/shared/actions/server/application/connector/methods/get_all/get_all.ts +++ b/x-pack/platform/plugins/shared/actions/server/application/connector/methods/get_all/get_all.ts @@ -8,7 +8,7 @@ /** * Get all actions with in-memory connectors */ -import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import * as estypes from '@elastic/elasticsearch/lib/api/types'; import { AuditLogger } from '@kbn/security-plugin-types-server'; import { ElasticsearchClient, Logger } from '@kbn/core/server'; import { omit } from 'lodash'; diff --git a/x-pack/platform/plugins/shared/actions/server/create_execute_function.test.ts b/x-pack/platform/plugins/shared/actions/server/create_execute_function.test.ts index 7be187743e634..cb8057d771013 100644 --- a/x-pack/platform/plugins/shared/actions/server/create_execute_function.test.ts +++ b/x-pack/platform/plugins/shared/actions/server/create_execute_function.test.ts @@ -16,6 +16,7 @@ import { asSavedObjectExecutionSource, } from './lib/action_execution_source'; import { actionsConfigMock } from './actions_config.mock'; +import { TaskPriority } from '@kbn/task-manager-plugin/server'; const mockTaskManager = taskManagerMock.createStart(); const savedObjectsClient = savedObjectsClientMock.create(); @@ -1189,4 +1190,210 @@ describe('bulkExecute()', () => { ] `); }); + + test('uses priority if specified', async () => { + mockTaskManager.aggregate.mockResolvedValue({ + took: 1, + timed_out: false, + _shards: { total: 1, successful: 1, skipped: 0, failed: 0 }, + hits: { total: { value: 2, relation: 'eq' }, max_score: null, hits: [] }, + aggregations: {}, + }); + mockActionsConfig.getMaxQueued.mockReturnValueOnce(3); + const executeFn = createBulkExecutionEnqueuerFunction({ + taskManager: mockTaskManager, + actionTypeRegistry: actionTypeRegistryMock.create(), + isESOCanEncrypt: true, + inMemoryConnectors: [], + configurationUtilities: mockActionsConfig, + logger: mockLogger, + }); + savedObjectsClient.bulkGet.mockResolvedValueOnce({ + saved_objects: [ + { id: '123', type: 'action', attributes: { actionTypeId: 'mock-action' }, references: [] }, + ], + }); + savedObjectsClient.bulkCreate.mockResolvedValueOnce({ + saved_objects: [ + { id: '234', type: 'action_task_params', attributes: { actionId: '123' }, references: [] }, + ], + }); + expect( + await executeFn(savedObjectsClient, [ + { + id: '123', + params: { baz: false }, + spaceId: 'default', + executionId: '123abc', + apiKey: null, + source: asHttpRequestExecutionSource(request), + actionTypeId: 'mock-action', + priority: TaskPriority.Low, + }, + { + id: '123', + params: { baz: false }, + spaceId: 'default', + executionId: '456xyz', + apiKey: null, + source: asHttpRequestExecutionSource(request), + actionTypeId: 'mock-action', + }, + ]) + ).toMatchInlineSnapshot(` + Object { + "errors": true, + "items": Array [ + Object { + "actionTypeId": "mock-action", + "id": "123", + "response": "success", + "uuid": undefined, + }, + Object { + "actionTypeId": "mock-action", + "id": "123", + "response": "queuedActionsLimitError", + "uuid": undefined, + }, + ], + } + `); + expect(mockTaskManager.bulkSchedule).toHaveBeenCalledTimes(1); + expect(mockTaskManager.bulkSchedule.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Array [ + Object { + "params": Object { + "actionTaskParamsId": "234", + "spaceId": "default", + }, + "priority": 1, + "scope": Array [ + "actions", + ], + "state": Object {}, + "taskType": "actions:mock-action", + }, + ], + ] + `); + }); + + test('uses apiKeyId if specified', async () => { + mockTaskManager.aggregate.mockResolvedValue({ + took: 1, + timed_out: false, + _shards: { total: 1, successful: 1, skipped: 0, failed: 0 }, + hits: { total: { value: 2, relation: 'eq' }, max_score: null, hits: [] }, + aggregations: {}, + }); + mockActionsConfig.getMaxQueued.mockReturnValueOnce(3); + const executeFn = createBulkExecutionEnqueuerFunction({ + taskManager: mockTaskManager, + actionTypeRegistry: actionTypeRegistryMock.create(), + isESOCanEncrypt: true, + inMemoryConnectors: [], + configurationUtilities: mockActionsConfig, + logger: mockLogger, + }); + savedObjectsClient.bulkGet.mockResolvedValueOnce({ + saved_objects: [ + { id: '123', type: 'action', attributes: { actionTypeId: 'mock-action' }, references: [] }, + ], + }); + savedObjectsClient.bulkCreate.mockResolvedValueOnce({ + saved_objects: [ + { id: '234', type: 'action_task_params', attributes: { actionId: '123' }, references: [] }, + ], + }); + expect( + await executeFn(savedObjectsClient, [ + { + id: '123', + params: { baz: false }, + spaceId: 'default', + executionId: '123abc', + apiKey: null, + source: asHttpRequestExecutionSource(request), + actionTypeId: 'mock-action', + apiKeyId: '235qgbdbqet', + }, + { + id: '123', + params: { baz: false }, + spaceId: 'default', + executionId: '456xyz', + apiKey: null, + source: asHttpRequestExecutionSource(request), + actionTypeId: 'mock-action', + apiKeyId: '235qgbdbqet', + }, + ]) + ).toMatchInlineSnapshot(` + Object { + "errors": true, + "items": Array [ + Object { + "actionTypeId": "mock-action", + "id": "123", + "response": "success", + "uuid": undefined, + }, + Object { + "actionTypeId": "mock-action", + "id": "123", + "response": "queuedActionsLimitError", + "uuid": undefined, + }, + ], + } + `); + + expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith( + [ + { + attributes: { + actionId: '123', + apiKey: null, + apiKeyId: '235qgbdbqet', + consumer: undefined, + executionId: '123abc', + params: { + baz: false, + }, + relatedSavedObjects: undefined, + source: 'HTTP_REQUEST', + }, + references: [ + { + id: '123', + name: 'actionRef', + type: 'action', + }, + ], + type: 'action_task_params', + }, + ], + { refresh: false } + ); + expect(mockTaskManager.bulkSchedule).toHaveBeenCalledTimes(1); + expect(mockTaskManager.bulkSchedule.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Array [ + Object { + "params": Object { + "actionTaskParamsId": "234", + "spaceId": "default", + }, + "scope": Array [ + "actions", + ], + "state": Object {}, + "taskType": "actions:mock-action", + }, + ], + ] + `); + }); }); diff --git a/x-pack/platform/plugins/shared/actions/server/create_execute_function.ts b/x-pack/platform/plugins/shared/actions/server/create_execute_function.ts index 539ada46a094a..4bfa992aae15f 100644 --- a/x-pack/platform/plugins/shared/actions/server/create_execute_function.ts +++ b/x-pack/platform/plugins/shared/actions/server/create_execute_function.ts @@ -6,7 +6,7 @@ */ import { SavedObjectsBulkResponse, SavedObjectsClientContract, Logger } from '@kbn/core/server'; -import { TaskManagerStartContract } from '@kbn/task-manager-plugin/server'; +import { TaskPriority, TaskManagerStartContract } from '@kbn/task-manager-plugin/server'; import { RawAction, ActionTypeRegistryContract, InMemoryConnector } from './types'; import { ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE } from './constants/saved_objects'; import { ExecuteOptions as ActionExecutorOptions } from './lib/action_executor'; @@ -28,9 +28,11 @@ export interface ExecuteOptions id: string; uuid?: string; spaceId: string; + apiKeyId?: string; apiKey: string | null; executionId: string; actionTypeId: string; + priority?: TaskPriority; } interface ActionTaskParams @@ -166,15 +168,17 @@ export function createBulkExecutionEnqueuerFunction({ executionId: actionToExecute.executionId, consumer: actionToExecute.consumer, relatedSavedObjects: relatedSavedObjectWithRefs, + apiKeyId: actionToExecute.apiKeyId, ...(actionToExecute.source ? { source: actionToExecute.source.type } : {}), }, references: taskReferences, }; }); + const actionTaskParamsRecords: SavedObjectsBulkResponse = await unsecuredSavedObjectsClient.bulkCreate(actions, { refresh: false }); - const taskInstances = actionTaskParamsRecords.saved_objects.map((so) => { + const taskInstances = actionTaskParamsRecords.saved_objects.map((so, index) => { const actionId = so.attributes.actionId; return { taskType: `actions:${actionTypeIds[actionId]}`, @@ -184,6 +188,7 @@ export function createBulkExecutionEnqueuerFunction({ }, state: {}, scope: ['actions'], + ...(runnableActions[index]?.priority ? { priority: runnableActions[index].priority } : {}), }; }); diff --git a/x-pack/platform/plugins/shared/actions/server/data/connector/types/params.ts b/x-pack/platform/plugins/shared/actions/server/data/connector/types/params.ts index c23447fb37486..9de712597ad60 100644 --- a/x-pack/platform/plugins/shared/actions/server/data/connector/types/params.ts +++ b/x-pack/platform/plugins/shared/actions/server/data/connector/types/params.ts @@ -6,7 +6,7 @@ */ import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; -import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import * as estypes from '@elastic/elasticsearch/lib/api/types'; import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; import { SavedObjectsClient } from '@kbn/core/server'; diff --git a/x-pack/platform/plugins/shared/actions/server/lib/get_execution_log_aggregation.ts b/x-pack/platform/plugins/shared/actions/server/lib/get_execution_log_aggregation.ts index ff11f831662cc..75c0dcdcdf74f 100644 --- a/x-pack/platform/plugins/shared/actions/server/lib/get_execution_log_aggregation.ts +++ b/x-pack/platform/plugins/shared/actions/server/lib/get_execution_log_aggregation.ts @@ -6,7 +6,7 @@ */ import { KueryNode } from '@kbn/es-query'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import Boom from '@hapi/boom'; import { flatMap, get, isEmpty } from 'lodash'; import { AggregateEventsBySavedObjectResult } from '@kbn/event-log-plugin/server'; diff --git a/x-pack/platform/plugins/shared/actions/server/monitoring/register_cluster_collector.ts b/x-pack/platform/plugins/shared/actions/server/monitoring/register_cluster_collector.ts index 23c4953b40d6e..b1ed0ecdf2ea8 100644 --- a/x-pack/platform/plugins/shared/actions/server/monitoring/register_cluster_collector.ts +++ b/x-pack/platform/plugins/shared/actions/server/monitoring/register_cluster_collector.ts @@ -7,7 +7,7 @@ import type { AggregationsKeyedPercentiles, AggregationsPercentilesAggregateBase, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import { MonitoringCollectionSetup } from '@kbn/monitoring-collection-plugin/server'; import { aggregateTaskOverduePercentilesForType } from '@kbn/task-manager-plugin/server'; import { CoreSetup } from '@kbn/core/server'; diff --git a/x-pack/platform/plugins/shared/actions/server/usage/actions_telemetry.ts b/x-pack/platform/plugins/shared/actions/server/usage/actions_telemetry.ts index b7e93f5157140..778313d2024a6 100644 --- a/x-pack/platform/plugins/shared/actions/server/usage/actions_telemetry.ts +++ b/x-pack/platform/plugins/shared/actions/server/usage/actions_telemetry.ts @@ -7,7 +7,7 @@ import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient, Logger } from '@kbn/core/server'; -import { AggregationsTermsAggregateBase } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { AggregationsTermsAggregateBase } from '@elastic/elasticsearch/lib/api/types'; import { AvgActionRunOutcomeByConnectorTypeBucket, parseActionRunOutcomeByConnectorTypesBucket, diff --git a/x-pack/platform/plugins/shared/actions/server/usage/lib/parse_connector_type_bucket.ts b/x-pack/platform/plugins/shared/actions/server/usage/lib/parse_connector_type_bucket.ts index 96e1610c635d8..936dc3f217ca2 100644 --- a/x-pack/platform/plugins/shared/actions/server/usage/lib/parse_connector_type_bucket.ts +++ b/x-pack/platform/plugins/shared/actions/server/usage/lib/parse_connector_type_bucket.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { AggregationsBuckets } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { AggregationsBuckets } from '@elastic/elasticsearch/lib/api/types'; import { replaceFirstAndLastDotSymbols } from '../actions_telemetry'; export interface AvgActionRunOutcomeByConnectorTypeBucket { diff --git a/x-pack/platform/plugins/shared/alerting/common/alert_schema/field_maps/mapping_from_field_map.ts b/x-pack/platform/plugins/shared/alerting/common/alert_schema/field_maps/mapping_from_field_map.ts index 1d5121883df69..67e41f6d9de6c 100644 --- a/x-pack/platform/plugins/shared/alerting/common/alert_schema/field_maps/mapping_from_field_map.ts +++ b/x-pack/platform/plugins/shared/alerting/common/alert_schema/field_maps/mapping_from_field_map.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { MappingTypeMapping } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { MappingTypeMapping } from '@elastic/elasticsearch/lib/api/types'; import { set } from '@kbn/safer-lodash-set'; import type { FieldMap, MultiField } from '@kbn/alerts-as-data-utils'; diff --git a/x-pack/platform/plugins/shared/alerting/common/rule_tags_aggregation.ts b/x-pack/platform/plugins/shared/alerting/common/rule_tags_aggregation.ts index 4df444d51e19b..bfdc244e9e116 100644 --- a/x-pack/platform/plugins/shared/alerting/common/rule_tags_aggregation.ts +++ b/x-pack/platform/plugins/shared/alerting/common/rule_tags_aggregation.ts @@ -8,7 +8,7 @@ import type { AggregationsAggregationContainer, AggregationsCompositeAggregation, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import type { AggregateOptions } from '../server/application/rule/methods/aggregate/types'; export type RuleTagsAggregationOptions = Pick & { diff --git a/x-pack/platform/plugins/shared/alerting/docs/openapi/paths/api@alerting@rule_types.yaml b/x-pack/platform/plugins/shared/alerting/docs/openapi/paths/api@alerting@rule_types.yaml index 378a8e0a7127c..e97477e5c11fe 100644 --- a/x-pack/platform/plugins/shared/alerting/docs/openapi/paths/api@alerting@rule_types.yaml +++ b/x-pack/platform/plugins/shared/alerting/docs/openapi/paths/api@alerting@rule_types.yaml @@ -71,7 +71,7 @@ get: description: type: string name: - type: string + type: string alerts: type: object description: > @@ -119,7 +119,7 @@ get: description: > A secondary alias. It is typically used to support the signals alias for detection rules. - shouldWrite: + shouldWrite: type: boolean description: > Indicates whether the rule should write out alerts as data. @@ -212,7 +212,7 @@ get: all: type: boolean read: - type: boolean + type: boolean category: type: string description: The rule category, which is used by features such as category-specific maintenance windows. @@ -234,7 +234,7 @@ get: description: Indicates whether the rule type has custom mappings for the alert data. has_fields_for_a_a_d: type: boolean - id: + id: description: The unique identifier for the rule type. type: string is_exportable: @@ -270,4 +270,4 @@ get: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_client/alerts_client.test.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_client/alerts_client.test.ts index 557341f3e02de..d6c147686c7a0 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_client/alerts_client.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_client/alerts_client.test.ts @@ -442,18 +442,16 @@ describe('Alerts Client', () => { ); expect(clusterClient.search).toHaveBeenCalledWith({ - body: { - query: { - bool: { - filter: [ - { term: { 'kibana.alert.rule.uuid': '1' } }, - { terms: { 'kibana.alert.uuid': ['abc', 'def', 'xyz'] } }, - ], - }, + query: { + bool: { + filter: [ + { term: { 'kibana.alert.rule.uuid': '1' } }, + { terms: { 'kibana.alert.uuid': ['abc', 'def', 'xyz'] } }, + ], }, - seq_no_primary_term: true, - size: 3, }, + seq_no_primary_term: true, + size: 3, index: useDataStreamForAlerts ? '.alerts-test.alerts-default' : '.internal.alerts-test.alerts-default-*', @@ -516,18 +514,16 @@ describe('Alerts Client', () => { ); expect(clusterClient.search).toHaveBeenCalledWith({ - body: { - query: { - bool: { - filter: [ - { term: { 'kibana.alert.rule.uuid': '1' } }, - { terms: { 'kibana.alert.uuid': ['abc'] } }, - ], - }, + query: { + bool: { + filter: [ + { term: { 'kibana.alert.rule.uuid': '1' } }, + { terms: { 'kibana.alert.uuid': ['abc'] } }, + ], }, - size: 1, - seq_no_primary_term: true, }, + size: 1, + seq_no_primary_term: true, index: useDataStreamForAlerts ? '.alerts-test.alerts-default' : '.internal.alerts-test.alerts-default-*', @@ -570,7 +566,7 @@ describe('Alerts Client', () => { index: '.alerts-test.alerts-default', refresh: 'wait_for', require_alias: !useDataStreamForAlerts, - body: [ + operations: [ { create: { _id: uuid1, ...(useDataStreamForAlerts ? {} : { require_alias: true }) }, }, @@ -617,7 +613,7 @@ describe('Alerts Client', () => { index: '.alerts-test.alerts-default', refresh: true, require_alias: !useDataStreamForAlerts, - body: [ + operations: [ { create: { _id: uuid1, ...(useDataStreamForAlerts ? {} : { require_alias: true }) }, }, @@ -710,7 +706,7 @@ describe('Alerts Client', () => { index: '.alerts-test.alerts-default', refresh: 'wait_for', require_alias: !useDataStreamForAlerts, - body: [ + operations: [ { index: { _id: 'abc', @@ -783,7 +779,7 @@ describe('Alerts Client', () => { index: '.alerts-test.alerts-default', refresh: 'wait_for', require_alias: !useDataStreamForAlerts, - body: [ + operations: [ { index: { _id: 'abc', @@ -918,7 +914,7 @@ describe('Alerts Client', () => { index: '.alerts-test.alerts-default', refresh: 'wait_for', require_alias: !useDataStreamForAlerts, - body: [ + operations: [ { create: { _id: 'abc', @@ -991,7 +987,7 @@ describe('Alerts Client', () => { index: '.alerts-test.alerts-default', refresh: 'wait_for', require_alias: !useDataStreamForAlerts, - body: [ + operations: [ { index: { _id: 'def', @@ -1090,7 +1086,7 @@ describe('Alerts Client', () => { index: '.alerts-test.alerts-default', refresh: 'wait_for', require_alias: !useDataStreamForAlerts, - body: [ + operations: [ { index: { _id: 'def', @@ -1247,7 +1243,7 @@ describe('Alerts Client', () => { index: '.alerts-test.alerts-default', refresh: 'wait_for', require_alias: !useDataStreamForAlerts, - body: [ + operations: [ { index: { _id: 'def', @@ -1365,7 +1361,7 @@ describe('Alerts Client', () => { index: '.alerts-test.alerts-default', refresh: 'wait_for', require_alias: !useDataStreamForAlerts, - body: [ + operations: [ { index: { _id: 'def', @@ -1569,7 +1565,7 @@ describe('Alerts Client', () => { index: '.alerts-test.alerts-default', refresh: 'wait_for', require_alias: !useDataStreamForAlerts, - body: [ + operations: [ { index: { _id: 'def', @@ -2540,7 +2536,7 @@ describe('Alerts Client', () => { index: '.alerts-test.alerts-default', refresh: 'wait_for', require_alias: !useDataStreamForAlerts, - body: [ + operations: [ { create: { _id: uuid1, ...(useDataStreamForAlerts ? {} : { require_alias: true }) }, }, @@ -2814,7 +2810,7 @@ describe('Alerts Client', () => { index: '.alerts-test.alerts-default', refresh: 'wait_for', require_alias: !useDataStreamForAlerts, - body: [ + operations: [ { create: { _id: expect.any(String), @@ -2915,7 +2911,7 @@ describe('Alerts Client', () => { index: '.alerts-test.alerts-default', refresh: 'wait_for', require_alias: !useDataStreamForAlerts, - body: [ + operations: [ { create: { _id: 'abc', @@ -3012,7 +3008,7 @@ describe('Alerts Client', () => { index: '.alerts-test.alerts-default', refresh: 'wait_for', require_alias: !useDataStreamForAlerts, - body: [ + operations: [ { index: { _id: 'abc', diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_client/alerts_client.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_client/alerts_client.ts index d62f579e4566e..ed42ae93fdcc3 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_client/alerts_client.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_client/alerts_client.ts @@ -15,7 +15,7 @@ import { ALERT_MAINTENANCE_WINDOW_IDS, } from '@kbn/rule-data-utils'; import { chunk, flatMap, get, isEmpty, keys } from 'lodash'; -import { SearchRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; import type { Alert } from '@kbn/alerts-as-data-utils'; import { DEFAULT_NAMESPACE_STRING } from '@kbn/core-saved-objects-utils-server'; import { DeepPartial } from '@kbn/utility-types'; @@ -231,7 +231,7 @@ export class AlertsClient< } public async search( - queryBody: SearchRequest['body'] + queryBody: SearchRequest ): Promise> { const esClient = await this.options.elasticsearchClientPromise; const index = this.isUsingDataStreams() @@ -242,7 +242,7 @@ export class AlertsClient< aggregations, } = await esClient.search({ index, - body: queryBody, + ...queryBody, ignore_unavailable: true, }); @@ -568,7 +568,7 @@ export class AlertsClient< refresh: this.isServerless ? true : 'wait_for', index: this.indexTemplateAndPattern.alias, require_alias: !this.isUsingDataStreams(), - body: bulkBody, + operations: bulkBody, }); // If there were individual indexing errors, they will be returned in the success response diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_client/alerts_client_fixtures.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_client/alerts_client_fixtures.ts index 0da20a5e49b70..90e8387f5039d 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_client/alerts_client_fixtures.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_client/alerts_client_fixtures.ts @@ -129,67 +129,66 @@ export const getExpectedQueryByExecutionUuid = ({ excludedAlertInstanceIds?: string[]; alertsFilter?: AlertsFilter; }) => ({ - body: { - query: { - bool: { - filter: [ - { term: { 'kibana.alert.rule.execution.uuid': uuid } }, - { term: { 'kibana.alert.rule.uuid': ruleId } }, - { - bool: { must_not: { exists: { field: 'kibana.alert.maintenance_window_ids' } } }, - }, - ...(isLifecycleAlert ? [{ term: { 'event.action': alertTypes[alertType] } }] : []), - ...(!!excludedAlertInstanceIds?.length - ? [ - { - bool: { - must_not: { - terms: { - 'kibana.alert.instance.id': excludedAlertInstanceIds, - }, + query: { + bool: { + filter: [ + { term: { 'kibana.alert.rule.execution.uuid': uuid } }, + { term: { 'kibana.alert.rule.uuid': ruleId } }, + { + bool: { must_not: { exists: { field: 'kibana.alert.maintenance_window_ids' } } }, + }, + ...(isLifecycleAlert ? [{ term: { 'event.action': alertTypes[alertType] } }] : []), + ...(!!excludedAlertInstanceIds?.length + ? [ + { + bool: { + must_not: { + terms: { + 'kibana.alert.instance.id': excludedAlertInstanceIds, }, }, }, - ] - : []), - ...(alertsFilter - ? [ - { - bool: { - minimum_should_match: 1, - should: [ - { - match: { - [alertsFilter.query!.kql.split(':')[0]]: - alertsFilter.query!.kql.split(':')[1], - }, + }, + ] + : []), + ...(alertsFilter + ? [ + { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + [alertsFilter.query!.kql.split(':')[0]]: + alertsFilter.query!.kql.split(':')[1], }, - ], - }, + }, + ], }, - { + }, + { + script: { script: { - script: { - params: { - datetimeField: '@timestamp', - days: alertsFilter.timeframe?.days, - timezone: alertsFilter.timeframe!.timezone, - }, - source: - 'params.days.contains(doc[params.datetimeField].value.withZoneSameInstant(ZoneId.of(params.timezone)).dayOfWeek.getValue())', + params: { + datetimeField: '@timestamp', + days: alertsFilter.timeframe?.days, + timezone: alertsFilter.timeframe!.timezone, }, + source: + 'params.days.contains(doc[params.datetimeField].value.withZoneSameInstant(ZoneId.of(params.timezone)).dayOfWeek.getValue())', }, }, - { + }, + { + script: { script: { - script: { - params: { - datetimeField: '@timestamp', - end: alertsFilter.timeframe!.hours.end, - start: alertsFilter.timeframe!.hours.start, - timezone: alertsFilter.timeframe!.timezone, - }, - source: ` + params: { + datetimeField: '@timestamp', + end: alertsFilter.timeframe!.hours.end, + start: alertsFilter.timeframe!.hours.start, + timezone: alertsFilter.timeframe!.timezone, + }, + source: ` def alertsDateTime = doc[params.datetimeField].value.withZoneSameInstant(ZoneId.of(params.timezone)); def alertsTime = LocalTime.of(alertsDateTime.getHour(), alertsDateTime.getMinute()); def start = LocalTime.parse(params.start); @@ -211,17 +210,16 @@ export const getExpectedQueryByExecutionUuid = ({ } } `, - }, }, }, - ] - : []), - ], - }, + }, + ] + : []), + ], }, - size: 100, - track_total_hits: true, }, + size: 100, + track_total_hits: true, ignore_unavailable: true, index: indexName, }); @@ -376,15 +374,13 @@ export const getExpectedQueryByTimeRange = ({ } return { - body: { - query: { - bool: { - filter, - }, + query: { + bool: { + filter, }, - size: 100, - track_total_hits: true, }, + size: 100, + track_total_hits: true, ignore_unavailable: true, index: indexName, }; diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_client/lib/get_summarized_alerts_query.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_client/lib/get_summarized_alerts_query.ts index ab3edece0becc..bb2bfeaa200fc 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_client/lib/get_summarized_alerts_query.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_client/lib/get_summarized_alerts_query.ts @@ -10,7 +10,7 @@ import { SearchRequest, SearchTotalHits, AggregationsAggregationContainer, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import { BoolQuery } from '@kbn/es-query'; import { ALERT_END, @@ -53,7 +53,7 @@ const getLifecycleAlertsQueryByExecutionUuid = ({ ruleId, excludedAlertInstanceIds, alertsFilter, -}: GetLifecycleAlertsQueryByExecutionUuidParams): Array => { +}: GetLifecycleAlertsQueryByExecutionUuidParams): SearchRequest[] => { // lifecycle alerts assign a different action to an alert depending // on whether it is new/ongoing/recovered. query for each action in order // to get the count of each action type as well as up to the maximum number @@ -89,7 +89,7 @@ const getLifecycleAlertsQueryByTimeRange = ({ ruleId, excludedAlertInstanceIds, alertsFilter, -}: GetLifecycleAlertsQueryByTimeRangeParams): Array => { +}: GetLifecycleAlertsQueryByTimeRangeParams): SearchRequest[] => { return [ getQueryByTimeRange({ start, @@ -124,7 +124,7 @@ const getQueryByExecutionUuid = ({ excludedAlertInstanceIds, action, alertsFilter, -}: GetQueryByExecutionUuidParams): SearchRequest['body'] => { +}: GetQueryByExecutionUuidParams): SearchRequest => { const filter: QueryDslQueryContainer[] = [ { term: { @@ -187,7 +187,7 @@ const getQueryByTimeRange = ({ excludedAlertInstanceIds, type, alertsFilter, -}: GetQueryByTimeRangeParams): SearchRequest['body'] => { +}: GetQueryByTimeRangeParams): SearchRequest => { // base query filters the alert documents for a rule by the given time range let filter: QueryDslQueryContainer[] = [ { @@ -282,7 +282,7 @@ export const getQueryByScopedQueries = ({ ruleId, action, maintenanceWindows, -}: GetQueryByScopedQueriesParams): SearchRequest['body'] => { +}: GetQueryByScopedQueriesParams): SearchRequest => { const filters: QueryDslQueryContainer[] = [ { term: { @@ -460,7 +460,7 @@ const getLifecycleAlertsQueries = ({ ruleId, excludedAlertInstanceIds, alertsFilter, -}: GetAlertsQueryParams): Array => { +}: GetAlertsQueryParams): SearchRequest[] => { let queryBodies; if (!!executionUuid) { queryBodies = getLifecycleAlertsQueryByExecutionUuid({ @@ -489,7 +489,7 @@ const getContinualAlertsQuery = ({ ruleId, excludedAlertInstanceIds, alertsFilter, -}: GetAlertsQueryParams): SearchRequest['body'] => { +}: GetAlertsQueryParams): SearchRequest => { let queryBody; if (!!executionUuid) { queryBody = getQueryByExecutionUuid({ @@ -516,7 +516,7 @@ const getMaintenanceWindowAlertsQuery = ({ ruleId, action, maintenanceWindows, -}: GetMaintenanceWindowAlertsQueryParams): SearchRequest['body'] => { +}: GetMaintenanceWindowAlertsQueryParams): SearchRequest => { return getQueryByScopedQueries({ executionUuid, ruleId, diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_client/lib/inject_analyze_wildcard.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_client/lib/inject_analyze_wildcard.ts index 58a4f89948973..2a6f6a3e0b754 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_client/lib/inject_analyze_wildcard.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_client/lib/inject_analyze_wildcard.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; export const injectAnalyzeWildcard = (query: QueryDslQueryContainer): void => { if (!query) { diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_client/lib/sanitize_bulk_response.test.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_client/lib/sanitize_bulk_response.test.ts index 533bb5b554ae9..383fc2123557f 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_client/lib/sanitize_bulk_response.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_client/lib/sanitize_bulk_response.test.ts @@ -5,7 +5,7 @@ * 2.0. */ import { TransportResult } from '@elastic/elasticsearch'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { sanitizeBulkErrorResponse } from './sanitize_bulk_response'; // Using https://www.elastic.co/guide/en/elasticsearch/reference/8.11/docs-bulk.html diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_client/lib/sanitize_bulk_response.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_client/lib/sanitize_bulk_response.ts index 0c18500c3bd5f..06d9debbbe2ef 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_client/lib/sanitize_bulk_response.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_client/lib/sanitize_bulk_response.ts @@ -8,7 +8,7 @@ import { cloneDeep } from 'lodash'; import { TransportResult } from '@elastic/elasticsearch'; import { get } from 'lodash'; import { set } from '@kbn/safer-lodash-set'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; export const sanitizeBulkErrorResponse = ( response: TransportResult | estypes.BulkResponse diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_service/alerts_service.test.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_service/alerts_service.test.ts index abf1d3d6c4307..a733a96e75216 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_service/alerts_service.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_service/alerts_service.test.ts @@ -10,7 +10,7 @@ import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-m import { IndicesGetDataStreamResponse, IndicesDataStreamIndex, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import { errors as EsErrors } from '@elastic/elasticsearch'; import { ReplaySubject, Subject, of } from 'rxjs'; import { AlertsService } from './alerts_service'; @@ -150,54 +150,52 @@ const getIndexTemplatePutBody = (opts?: GetIndexTemplatePutBodyOpts) => { ]; return { name: `.alerts-${context ? context : 'test'}.alerts-${namespace}-index-template`, - body: { - index_patterns: indexPatterns, - composed_of: [ - ...(useEcs ? ['.alerts-ecs-mappings'] : []), - `.alerts-${context ? `${context}.alerts` : 'test.alerts'}-mappings`, - ...(useLegacyAlerts ? ['.alerts-legacy-alert-mappings'] : []), - '.alerts-framework-mappings', - ], - ...(useDataStream ? { data_stream: { hidden: true } } : {}), - priority: namespace.length, - template: { - settings: { - auto_expand_replicas: '0-1', - hidden: true, - ...(useDataStream - ? {} - : { - 'index.lifecycle': { - name: '.alerts-ilm-policy', - rollover_alias: `.alerts-${context ? context : 'test'}.alerts-${namespace}`, - }, - }), - 'index.mapping.ignore_malformed': true, - 'index.mapping.total_fields.limit': 2500, - }, - mappings: { - dynamic: false, - _meta: { - kibana: { version: '8.8.0' }, - managed: true, - namespace, - }, - }, - ...(secondaryAlias - ? { - aliases: { - [`${secondaryAlias}-default`]: { - is_write_index: false, - }, + index_patterns: indexPatterns, + composed_of: [ + ...(useEcs ? ['.alerts-ecs-mappings'] : []), + `.alerts-${context ? `${context}.alerts` : 'test.alerts'}-mappings`, + ...(useLegacyAlerts ? ['.alerts-legacy-alert-mappings'] : []), + '.alerts-framework-mappings', + ], + ...(useDataStream ? { data_stream: { hidden: true } } : {}), + priority: namespace.length, + template: { + settings: { + auto_expand_replicas: '0-1', + hidden: true, + ...(useDataStream + ? {} + : { + 'index.lifecycle': { + name: '.alerts-ilm-policy', + rollover_alias: `.alerts-${context ? context : 'test'}.alerts-${namespace}`, }, - } - : {}), + }), + 'index.mapping.ignore_malformed': true, + 'index.mapping.total_fields.limit': 2500, }, - _meta: { - kibana: { version: '8.8.0' }, - managed: true, - namespace, + mappings: { + dynamic: false, + _meta: { + kibana: { version: '8.8.0' }, + managed: true, + namespace, + }, }, + ...(secondaryAlias + ? { + aliases: { + [`${secondaryAlias}-default`]: { + is_write_index: false, + }, + }, + } + : {}), + }, + _meta: { + kibana: { version: '8.8.0' }, + managed: true, + namespace, }, }; }; @@ -473,14 +471,12 @@ describe('Alerts Service', () => { expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledTimes(1); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith({ name: existingIndexTemplate.name, - body: { - ...existingIndexTemplate.index_template, - template: { - ...existingIndexTemplate.index_template.template, - settings: { - ...existingIndexTemplate.index_template.template?.settings, - 'index.mapping.total_fields.limit': 2500, - }, + ...existingIndexTemplate.index_template, + template: { + ...existingIndexTemplate.index_template.template, + settings: { + ...existingIndexTemplate.index_template.template?.settings, + 'index.mapping.total_fields.limit': 2500, }, }, }); @@ -558,11 +554,9 @@ describe('Alerts Service', () => { } else { expect(clusterClient.indices.create).toHaveBeenCalledWith({ index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - }, + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, }, }, }); @@ -624,11 +618,9 @@ describe('Alerts Service', () => { } else { expect(clusterClient.indices.create).toHaveBeenCalledWith({ index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - }, + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, }, }, }); @@ -686,11 +678,9 @@ describe('Alerts Service', () => { } else { expect(clusterClient.indices.create).toHaveBeenCalledWith({ index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - }, + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, }, }, }); @@ -731,11 +721,9 @@ describe('Alerts Service', () => { } else { expect(clusterClient.indices.create).toHaveBeenNthCalledWith(1, { index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - }, + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, }, }, }); @@ -798,11 +786,9 @@ describe('Alerts Service', () => { } else { expect(clusterClient.indices.create).toHaveBeenNthCalledWith(2, { index: '.internal.alerts-test.alerts-another-namespace-000001', - body: { - aliases: { - '.alerts-test.alerts-another-namespace': { - is_write_index: true, - }, + aliases: { + '.alerts-test.alerts-another-namespace': { + is_write_index: true, }, }, }); @@ -855,11 +841,9 @@ describe('Alerts Service', () => { expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(2); expect(clusterClient.indices.create).toHaveBeenCalledWith({ index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - }, + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, }, }, }); @@ -891,46 +875,44 @@ describe('Alerts Service', () => { const template = { name: `.alerts-empty.alerts-default-index-template`, - body: { - index_patterns: useDataStreamForAlerts - ? [`.alerts-empty.alerts-default`] - : [ - `.internal.alerts-empty.alerts-default-*`, - `.reindexed-v8-internal.alerts-empty.alerts-default-*`, - ], - composed_of: ['.alerts-framework-mappings'], - ...(useDataStreamForAlerts ? { data_stream: { hidden: true } } : {}), - priority: 7, - template: { - settings: { - auto_expand_replicas: '0-1', - hidden: true, - ...(useDataStreamForAlerts - ? {} - : { - 'index.lifecycle': { - name: '.alerts-ilm-policy', - rollover_alias: `.alerts-empty.alerts-default`, - }, - }), - 'index.mapping.ignore_malformed': true, - 'index.mapping.total_fields.limit': 2500, - }, - mappings: { - _meta: { - kibana: { version: '8.8.0' }, - managed: true, - namespace: 'default', - }, - dynamic: false, - }, + index_patterns: useDataStreamForAlerts + ? [`.alerts-empty.alerts-default`] + : [ + `.internal.alerts-empty.alerts-default-*`, + `.reindexed-v8-internal.alerts-empty.alerts-default-*`, + ], + composed_of: ['.alerts-framework-mappings'], + ...(useDataStreamForAlerts ? { data_stream: { hidden: true } } : {}), + priority: 7, + template: { + settings: { + auto_expand_replicas: '0-1', + hidden: true, + ...(useDataStreamForAlerts + ? {} + : { + 'index.lifecycle': { + name: '.alerts-ilm-policy', + rollover_alias: `.alerts-empty.alerts-default`, + }, + }), + 'index.mapping.ignore_malformed': true, + 'index.mapping.total_fields.limit': 2500, }, - _meta: { - kibana: { version: '8.8.0' }, - managed: true, - namespace: 'default', + mappings: { + _meta: { + kibana: { version: '8.8.0' }, + managed: true, + namespace: 'default', + }, + dynamic: false, }, }, + _meta: { + kibana: { version: '8.8.0' }, + managed: true, + namespace: 'default', + }, }; expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith(template); @@ -944,11 +926,9 @@ describe('Alerts Service', () => { } else { expect(clusterClient.indices.create).toHaveBeenCalledWith({ index: '.internal.alerts-empty.alerts-default-000001', - body: { - aliases: { - '.alerts-empty.alerts-default': { - is_write_index: true, - }, + aliases: { + '.alerts-empty.alerts-default': { + is_write_index: true, }, }, }); diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_service/default_lifecycle_policy.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_service/default_lifecycle_policy.ts index 67230f1c35da0..e6717f408b342 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_service/default_lifecycle_policy.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_service/default_lifecycle_policy.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IlmPolicy } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { IlmPolicy } from '@elastic/elasticsearch/lib/api/types'; /** * Default alert index ILM policy diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_concrete_write_index.test.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_concrete_write_index.test.ts index f8e2f8c089529..2683007ca86f4 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_concrete_write_index.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_concrete_write_index.test.ts @@ -6,7 +6,7 @@ */ import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; import { errors as EsErrors } from '@elastic/elasticsearch'; -import { IndicesGetDataStreamResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { IndicesGetDataStreamResponse } from '@elastic/elasticsearch/lib/api/types'; import { createConcreteWriteIndex, setConcreteWriteIndex } from './create_concrete_write_index'; import { getDataStreamAdapter } from './data_stream_adapter'; @@ -95,11 +95,9 @@ describe('createConcreteWriteIndex', () => { } else { expect(clusterClient.indices.create).toHaveBeenCalledWith({ index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - }, + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, }, }, }); @@ -309,11 +307,9 @@ describe('createConcreteWriteIndex', () => { } else { expect(clusterClient.indices.create).toHaveBeenCalledWith({ index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - }, + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, }, }, }); @@ -359,11 +355,9 @@ describe('createConcreteWriteIndex', () => { if (!useDataStream) { expect(clusterClient.indices.create).toHaveBeenCalledWith({ index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - }, + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, }, }, }); @@ -399,11 +393,9 @@ describe('createConcreteWriteIndex', () => { if (!useDataStream) { expect(clusterClient.indices.create).toHaveBeenCalledWith({ index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - }, + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, }, }, }); @@ -631,11 +623,9 @@ describe('createConcreteWriteIndex', () => { } else { expect(clusterClient.indices.create).toHaveBeenCalledWith({ index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - }, + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, }, }, }); @@ -670,11 +660,9 @@ describe('createConcreteWriteIndex', () => { } else { expect(clusterClient.indices.create).toHaveBeenCalledWith({ index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - }, + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, }, }, }); @@ -756,23 +744,21 @@ describe('setConcreteWriteIndex', () => { 'Attempting to set index: .internal.alerts-test.alerts-default-000004 as the write index for alias: .alerts-test.alerts-default.' ); expect(clusterClient.indices.updateAliases).toHaveBeenCalledWith({ - body: { - actions: [ - { - remove: { - alias: '.alerts-test.alerts-default', - index: '.internal.alerts-test.alerts-default-000004', - }, + actions: [ + { + remove: { + alias: '.alerts-test.alerts-default', + index: '.internal.alerts-test.alerts-default-000004', }, - { - add: { - alias: '.alerts-test.alerts-default', - index: '.internal.alerts-test.alerts-default-000004', - is_write_index: true, - }, + }, + { + add: { + alias: '.alerts-test.alerts-default', + index: '.internal.alerts-test.alerts-default-000004', + is_write_index: true, }, - ], - }, + }, + ], }); expect(logger.info).toHaveBeenCalledWith( 'Successfully set index: .internal.alerts-test.alerts-default-000004 as the write index for alias: .alerts-test.alerts-default.' diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_concrete_write_index.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_concrete_write_index.ts index cc298ed3cd7d2..7bb7a9d2a76bb 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_concrete_write_index.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_concrete_write_index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IndicesSimulateIndexTemplateResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { IndicesSimulateIndexTemplateResponse } from '@elastic/elasticsearch/lib/api/types'; import { Logger, ElasticsearchClient } from '@kbn/core/server'; import { get, sortBy } from 'lodash'; import { IIndexPatternString } from '../resource_installer_utils'; @@ -45,7 +45,7 @@ const updateTotalFieldLimitSetting = async ({ () => esClient.indices.putSettings({ index, - body: { 'index.mapping.total_fields.limit': totalFieldsLimit }, + settings: { 'index.mapping.total_fields.limit': totalFieldsLimit }, }), { logger } ); @@ -90,7 +90,7 @@ const updateUnderlyingMapping = async ({ try { await retryTransientEsErrors( - () => esClient.indices.putMapping({ index, body: simulatedMapping }), + () => esClient.indices.putMapping({ index, ...simulatedMapping }), { logger } ); @@ -183,18 +183,16 @@ export async function setConcreteWriteIndex(opts: SetConcreteWriteIndexOpts) { await retryTransientEsErrors( () => esClient.indices.updateAliases({ - body: { - actions: [ - { remove: { index: concreteIndex.index, alias: concreteIndex.alias } }, - { - add: { - index: concreteIndex.index, - alias: concreteIndex.alias, - is_write_index: true, - }, + actions: [ + { remove: { index: concreteIndex.index, alias: concreteIndex.alias } }, + { + add: { + index: concreteIndex.index, + alias: concreteIndex.alias, + is_write_index: true, }, - ], - }, + }, + ], }), { logger } ); diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_component_template.test.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_component_template.test.ts index 3a1d490afe9d6..e1ea7a3e519da 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_component_template.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_component_template.test.ts @@ -5,6 +5,7 @@ * 2.0. */ import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; +import { ClusterPutComponentTemplateRequest } from '@elastic/elasticsearch/lib/api/types'; import { errors as EsErrors } from '@elastic/elasticsearch'; import { createOrUpdateComponentTemplate } from './create_or_update_component_template'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; @@ -13,7 +14,7 @@ const randomDelayMultiplier = 0.01; const logger = loggingSystemMock.createLogger(); const clusterClient = elasticsearchServiceMock.createClusterClient().asInternalUser; -const ComponentTemplate = { +const ComponentTemplate: ClusterPutComponentTemplateRequest = { name: 'test-mappings', _meta: { managed: true, @@ -176,14 +177,12 @@ describe('createOrUpdateComponentTemplate', () => { expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledTimes(1); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith({ name: existingIndexTemplate.name, - body: { - ...existingIndexTemplate.index_template, - template: { - ...existingIndexTemplate.index_template.template, - settings: { - ...existingIndexTemplate.index_template.template?.settings, - 'index.mapping.total_fields.limit': 2500, - }, + ...existingIndexTemplate.index_template, + template: { + ...existingIndexTemplate.index_template.template, + settings: { + ...existingIndexTemplate.index_template.template?.settings, + 'index.mapping.total_fields.limit': 2500, }, }, }); @@ -282,14 +281,12 @@ describe('createOrUpdateComponentTemplate', () => { expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledTimes(1); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith({ name: existingIndexTemplate.name, - body: { - ...existingIndexTemplate.index_template, - template: { - ...existingIndexTemplate.index_template.template, - settings: { - ...existingIndexTemplate.index_template.template?.settings, - 'index.mapping.total_fields.limit': 2500, - }, + ...existingIndexTemplate.index_template, + template: { + ...existingIndexTemplate.index_template.template, + settings: { + ...existingIndexTemplate.index_template.template?.settings, + 'index.mapping.total_fields.limit': 2500, }, }, }); diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_component_template.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_component_template.ts index 118ad5de97198..14c2b6876071a 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_component_template.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_component_template.ts @@ -8,7 +8,7 @@ import { ClusterPutComponentTemplateRequest, IndicesGetIndexTemplateIndexTemplateItem, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import { Logger, ElasticsearchClient } from '@kbn/core/server'; import { asyncForEach } from '@kbn/std'; import { retryTransientEsErrors } from './retry_transient_es_errors'; @@ -50,14 +50,12 @@ const getIndexTemplatesUsingComponentTemplate = async ( () => esClient.indices.putIndexTemplate({ name: template.name, - body: { - ...template.index_template, - template: { - ...template.index_template.template, - settings: { - ...template.index_template.template?.settings, - 'index.mapping.total_fields.limit': totalFieldsLimit, - }, + ...template.index_template, + template: { + ...template.index_template.template, + settings: { + ...template.index_template.template?.settings, + 'index.mapping.total_fields.limit': totalFieldsLimit, }, }, }), diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_ilm_policy.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_ilm_policy.ts index 4ba14dbe3956b..aabdfbf5dde52 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_ilm_policy.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_ilm_policy.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IlmPolicy } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { IlmPolicy } from '@elastic/elasticsearch/lib/api/types'; import { Logger, ElasticsearchClient } from '@kbn/core/server'; import { retryTransientEsErrors } from './retry_transient_es_errors'; import { DataStreamAdapter } from './data_stream_adapter'; diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_index_template.test.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_index_template.test.ts index 85113b768860a..b130976f6bcb0 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_index_template.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_index_template.test.ts @@ -16,44 +16,42 @@ const clusterClient = elasticsearchServiceMock.createClusterClient().asInternalU const IndexTemplate = (namespace: string = 'default', useDataStream: boolean = false) => ({ name: `.alerts-test.alerts-${namespace}-index-template`, - body: { - _meta: { - kibana: { - version: '8.6.1', - }, - managed: true, - namespace, + _meta: { + kibana: { + version: '8.6.1', }, - composed_of: ['mappings1', 'framework-mappings'], - index_patterns: [`.internal.alerts-test.alerts-${namespace}-*`], - template: { - mappings: { - _meta: { - kibana: { - version: '8.6.1', - }, - managed: true, - namespace, + managed: true, + namespace, + }, + composed_of: ['mappings1', 'framework-mappings'], + index_patterns: [`.internal.alerts-test.alerts-${namespace}-*`], + template: { + mappings: { + _meta: { + kibana: { + version: '8.6.1', }, - dynamic: false, - }, - settings: { - auto_expand_replicas: '0-1', - hidden: true, - ...(useDataStream - ? {} - : { - 'index.lifecycle': { - name: 'test-ilm-policy', - rollover_alias: `.alerts-test.alerts-${namespace}`, - }, - }), - 'index.mapping.ignore_malformed': true, - 'index.mapping.total_fields.limit': 2500, + managed: true, + namespace, }, + dynamic: false, + }, + settings: { + auto_expand_replicas: '0-1', + hidden: true, + ...(useDataStream + ? {} + : { + 'index.lifecycle': { + name: 'test-ilm-policy', + rollover_alias: `.alerts-test.alerts-${namespace}`, + }, + }), + 'index.mapping.ignore_malformed': true, + 'index.mapping.total_fields.limit': 2500, }, - priority: namespace.length, }, + priority: namespace.length, }); const SimulateTemplateResponse = { diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_index_template.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_index_template.ts index 0a1b4951bcc9a..d54d9cd09572a 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_index_template.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/create_or_update_index_template.ts @@ -9,7 +9,7 @@ import { IndicesPutIndexTemplateRequest, MappingTypeMapping, Metadata, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import { Logger, ElasticsearchClient } from '@kbn/core/server'; import { isEmpty } from 'lodash'; import { IIndexPatternString } from '../resource_installer_utils'; @@ -57,42 +57,40 @@ export const getIndexTemplate = ({ return { name: indexPatterns.template, - body: { - ...(dataStreamFields.data_stream ? { data_stream: dataStreamFields.data_stream } : {}), - index_patterns: dataStreamFields.index_patterns, - composed_of: componentTemplateRefs, - template: { - settings: { - auto_expand_replicas: '0-1', - hidden: true, - ...(dataStreamAdapter.isUsingDataStreams() - ? {} - : { - 'index.lifecycle': indexLifecycle, - }), - 'index.mapping.ignore_malformed': true, - 'index.mapping.total_fields.limit': totalFieldsLimit, - }, - mappings: { - dynamic: false, - _meta: indexMetadata, - }, - ...(indexPatterns.secondaryAlias - ? { - aliases: { - [indexPatterns.secondaryAlias]: { - is_write_index: false, - }, - }, - } - : {}), + ...(dataStreamFields.data_stream ? { data_stream: dataStreamFields.data_stream } : {}), + index_patterns: dataStreamFields.index_patterns, + composed_of: componentTemplateRefs, + template: { + settings: { + auto_expand_replicas: '0-1', + hidden: true, + ...(dataStreamAdapter.isUsingDataStreams() + ? {} + : { + 'index.lifecycle': indexLifecycle, + }), + 'index.mapping.ignore_malformed': true, + 'index.mapping.total_fields.limit': totalFieldsLimit, }, - _meta: indexMetadata, - - // By setting the priority to namespace.length, we ensure that if one namespace is a prefix of another namespace - // then newly created indices will use the matching template with the *longest* namespace - priority: namespace.length, + mappings: { + dynamic: false, + _meta: indexMetadata, + }, + ...(indexPatterns.secondaryAlias + ? { + aliases: { + [indexPatterns.secondaryAlias]: { + is_write_index: false, + }, + }, + } + : {}), }, + _meta: indexMetadata, + + // By setting the priority to namespace.length, we ensure that if one namespace is a prefix of another namespace + // then newly created indices will use the matching template with the *longest* namespace + priority: namespace.length, }; }; diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/data_stream_adapter.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/data_stream_adapter.ts index a4805cd95c5ff..5293cc73c1100 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/data_stream_adapter.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/data_stream_adapter.ts @@ -208,11 +208,9 @@ async function createAliasStream(opts: CreateConcreteWriteIndexOpts): Promise esClient.indices.create({ index: indexPatterns.name, - body: { - aliases: { - [indexPatterns.alias]: { - is_write_index: true, - }, + aliases: { + [indexPatterns.alias]: { + is_write_index: true, }, }, }), diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/set_alerts_to_untracked.test.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/set_alerts_to_untracked.test.ts index 003673f9fdb92..5c911ed35a2e7 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/set_alerts_to_untracked.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/set_alerts_to_untracked.test.ts @@ -59,42 +59,45 @@ describe('setAlertsToUntracked()', () => { Array [ Object { "allow_no_indices": true, - "body": Object { - "conflicts": "proceed", - "query": Object { - "bool": Object { - "must": Array [ - Object { - "term": Object { - "kibana.alert.status": Object { - "value": "active", - }, + "conflicts": "proceed", + "index": Array [ + "test-index", + ], + "query": Object { + "bool": Object { + "must": Array [ + Object { + "term": Object { + "kibana.alert.status": Object { + "value": "active", }, }, - Object { - "bool": Object { - "should": Array [ - Object { - "term": Object { - "kibana.alert.rule.uuid": Object { - "value": "test-rule", - }, + }, + Object { + "bool": Object { + "should": Array [ + Object { + "term": Object { + "kibana.alert.rule.uuid": Object { + "value": "test-rule", }, }, - ], - }, + }, + ], }, - Object { - "bool": Object { - "should": Array [], - }, + }, + Object { + "bool": Object { + "should": Array [], }, - ], - }, + }, + ], }, - "script": Object { - "lang": "painless", - "source": " + }, + "refresh": true, + "script": Object { + "lang": "painless", + "source": " if (!ctx._source.containsKey('kibana.alert.status') || ctx._source['kibana.alert.status'].empty) { ctx._source.kibana.alert.status = 'untracked'; ctx._source.kibana.alert.end = '2023-03-28T22:27:28.159Z'; @@ -104,12 +107,7 @@ describe('setAlertsToUntracked()', () => { ctx._source['kibana.alert.end'] = '2023-03-28T22:27:28.159Z'; ctx._source['kibana.alert.time_range'].lte = '2023-03-28T22:27:28.159Z'; }", - }, }, - "index": Array [ - "test-index", - ], - "refresh": true, }, ] `); @@ -128,42 +126,45 @@ describe('setAlertsToUntracked()', () => { Array [ Object { "allow_no_indices": true, - "body": Object { - "conflicts": "proceed", - "query": Object { - "bool": Object { - "must": Array [ - Object { - "term": Object { - "kibana.alert.status": Object { - "value": "active", - }, + "conflicts": "proceed", + "index": Array [ + "test-index", + ], + "query": Object { + "bool": Object { + "must": Array [ + Object { + "term": Object { + "kibana.alert.status": Object { + "value": "active", }, }, - Object { - "bool": Object { - "should": Array [], - }, + }, + Object { + "bool": Object { + "should": Array [], }, - Object { - "bool": Object { - "should": Array [ - Object { - "term": Object { - "kibana.alert.uuid": Object { - "value": "test-alert", - }, + }, + Object { + "bool": Object { + "should": Array [ + Object { + "term": Object { + "kibana.alert.uuid": Object { + "value": "test-alert", }, }, - ], - }, + }, + ], }, - ], - }, + }, + ], }, - "script": Object { - "lang": "painless", - "source": " + }, + "refresh": true, + "script": Object { + "lang": "painless", + "source": " if (!ctx._source.containsKey('kibana.alert.status') || ctx._source['kibana.alert.status'].empty) { ctx._source.kibana.alert.status = 'untracked'; ctx._source.kibana.alert.end = '2023-03-28T22:27:28.159Z'; @@ -173,12 +174,7 @@ describe('setAlertsToUntracked()', () => { ctx._source['kibana.alert.end'] = '2023-03-28T22:27:28.159Z'; ctx._source['kibana.alert.time_range'].lte = '2023-03-28T22:27:28.159Z'; }", - }, }, - "index": Array [ - "test-index", - ], - "refresh": true, }, ] `); @@ -457,63 +453,59 @@ describe('setAlertsToUntracked()', () => { expect(clusterClient.updateByQuery).toHaveBeenCalledWith( expect.objectContaining({ - body: expect.objectContaining({ - query: { - bool: { - must: [ - { - term: { - 'kibana.alert.status': { - value: 'active', // This has to be active - }, + query: { + bool: { + must: [ + { + term: { + 'kibana.alert.status': { + value: 'active', // This has to be active }, }, - ], - filter: [ - { - bool: { - must: { - term: { - 'kibana.alert.rule.name': 'test', - }, + }, + ], + filter: [ + { + bool: { + must: { + term: { + 'kibana.alert.rule.name': 'test', }, }, }, - ], - }, + }, + ], }, - }), + }, }) ); expect(clusterClient.search).toHaveBeenCalledWith( expect.objectContaining({ - body: expect.objectContaining({ - query: { - bool: { - must: [ - { - term: { - 'kibana.alert.status': { - value: 'untracked', // This has to be untracked - }, + query: { + bool: { + must: [ + { + term: { + 'kibana.alert.status': { + value: 'untracked', // This has to be untracked }, }, - ], - filter: [ - { - bool: { - must: { - term: { - 'kibana.alert.rule.name': 'test', - }, + }, + ], + filter: [ + { + bool: { + must: { + term: { + 'kibana.alert.rule.name': 'test', }, }, }, - ], - }, + }, + ], }, - }), + }, }) ); @@ -596,32 +588,30 @@ describe('setAlertsToUntracked()', () => { expect(clusterClient.updateByQuery).toHaveBeenCalledWith( expect.objectContaining({ - body: expect.objectContaining({ - query: { - bool: { - must: [ - { - term: { - 'kibana.alert.status': { - value: 'active', // This has to be active - }, + query: { + bool: { + must: [ + { + term: { + 'kibana.alert.status': { + value: 'active', // This has to be active }, }, - ], - filter: [ - { - bool: { - must: { - term: { - 'kibana.alert.rule.name': 'test', - }, + }, + ], + filter: [ + { + bool: { + must: { + term: { + 'kibana.alert.rule.name': 'test', }, }, }, - ], - }, + }, + ], }, - }), + }, }) ); diff --git a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/set_alerts_to_untracked.ts b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/set_alerts_to_untracked.ts index 89c8d671de6a0..6389f4e6639db 100644 --- a/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/set_alerts_to_untracked.ts +++ b/x-pack/platform/plugins/shared/alerting/server/alerts_service/lib/set_alerts_to_untracked.ts @@ -20,7 +20,7 @@ import { ALERT_UUID, AlertStatus, } from '@kbn/rule-data-utils'; -import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; import type { RulesClientContext } from '../../rules_client'; import { AlertingAuthorizationEntity } from '../../authorization/types'; @@ -125,14 +125,12 @@ const ensureAuthorizedToUntrack = async (params: SetAlertsToUntrackedParamsWithD const response = await esClient.search({ index: indices, allow_no_indices: true, - body: { - size: 0, - query: getUntrackQuery(params, ALERT_STATUS_ACTIVE), - aggs: { - ruleTypeIds: { - terms: { field: ALERT_RULE_TYPE_ID }, - aggs: { consumers: { terms: { field: ALERT_RULE_CONSUMER } } }, - }, + size: 0, + query: getUntrackQuery(params, ALERT_STATUS_ACTIVE), + aggs: { + ruleTypeIds: { + terms: { field: ALERT_RULE_TYPE_ID }, + aggs: { consumers: { terms: { field: ALERT_RULE_CONSUMER } } }, }, }, }); @@ -218,14 +216,12 @@ export async function setAlertsToUntracked( const response = await esClient.updateByQuery({ index: indices, allow_no_indices: true, - body: { - conflicts: 'proceed', - script: { - source: getUntrackUpdatePainlessScript(new Date()), - lang: 'painless', - }, - query: getUntrackQuery(params, ALERT_STATUS_ACTIVE), + conflicts: 'proceed', + script: { + source: getUntrackUpdatePainlessScript(new Date()), + lang: 'painless', }, + query: getUntrackQuery(params, ALERT_STATUS_ACTIVE), refresh: true, }); @@ -259,11 +255,9 @@ export async function setAlertsToUntracked( const searchResponse = await esClient.search({ index: indices, allow_no_indices: true, - body: { - _source: [ALERT_RULE_UUID, ALERT_UUID], - size: total, - query: getUntrackQuery(params, ALERT_STATUS_UNTRACKED), - }, + _source: [ALERT_RULE_UUID, ALERT_UUID], + size: total, + query: getUntrackQuery(params, ALERT_STATUS_UNTRACKED), }); return searchResponse.hits.hits.map((hit) => hit._source) as UntrackedAlertsResult; diff --git a/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/delete/delete_backfill.test.ts b/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/delete/delete_backfill.test.ts index b0879613d069f..d31c830c970ca 100644 --- a/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/delete/delete_backfill.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/delete/delete_backfill.test.ts @@ -85,8 +85,8 @@ const mockAdHocRunSO: SavedObject = { name: fakeRuleName, tags: ['foo'], alertTypeId: 'myType', - // @ts-expect-error params: {}, + actions: [], apiKeyOwner: 'user', apiKeyCreatedByUser: false, consumer: 'myApp', diff --git a/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/find/find_backfill.test.ts b/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/find/find_backfill.test.ts index ade1a1f35b59e..7f140622310be 100644 --- a/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/find/find_backfill.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/find/find_backfill.test.ts @@ -6,7 +6,7 @@ */ import { ActionsAuthorization } from '@kbn/actions-plugin/server'; -import { actionsAuthorizationMock } from '@kbn/actions-plugin/server/mocks'; +import { actionsAuthorizationMock, actionsClientMock } from '@kbn/actions-plugin/server/mocks'; import { RULE_SAVED_OBJECT_TYPE } from '../../../..'; import { AlertingAuthorization } from '../../../../authorization'; import { alertingAuthorizationMock } from '../../../../authorization/alerting_authorization.mock'; @@ -22,7 +22,7 @@ import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/s import { fromKueryExpression } from '@kbn/es-query'; import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; import { taskManagerMock } from '@kbn/task-manager-plugin/server/mocks'; -import { ConstructorOptions, RulesClient } from '../../../../rules_client'; +import { RulesClient } from '../../../../rules_client'; import { adHocRunStatus } from '../../../../../common/constants'; import { ConnectorAdapterRegistry } from '../../../../connector_adapters/connector_adapter_registry'; import { SavedObject } from '@kbn/core/server'; @@ -142,35 +142,7 @@ const authDslFilter = { type: 'function', }; -const rulesClientParams: jest.Mocked = { - taskManager, - ruleTypeRegistry, - unsecuredSavedObjectsClient, - authorization: authorization as unknown as AlertingAuthorization, - actionsAuthorization: actionsAuthorization as unknown as ActionsAuthorization, - spaceId: 'default', - namespace: 'default', - getUserName: jest.fn(), - createAPIKey: jest.fn(), - logger: loggingSystemMock.create().get(), - internalSavedObjectsRepository, - encryptedSavedObjectsClient: encryptedSavedObjects, - getActionsClient: jest.fn(), - getEventLogClient: jest.fn(), - kibanaVersion, - auditLogger, - maxScheduledPerMinute: 10000, - minimumScheduleInterval: { value: '1m', enforce: false }, - isAuthenticationTypeAPIKey: jest.fn(), - getAuthenticationAPIKey: jest.fn(), - getAlertIndicesAlias: jest.fn(), - alertsService: null, - backfillClient, - isSystemAction: jest.fn(), - connectorAdapterRegistry: new ConnectorAdapterRegistry(), - uiSettings: uiSettingsServiceMock.createStartContract(), -}; - +const mockActionsClient = actionsClientMock.create(); const fakeRuleName = 'fakeRuleName'; const mockAdHocRunSO: SavedObject = { @@ -186,7 +158,6 @@ const mockAdHocRunSO: SavedObject = { name: fakeRuleName, tags: ['foo'], alertTypeId: 'myType', - // @ts-expect-error params: {}, apiKeyOwner: 'user', apiKeyCreatedByUser: false, @@ -195,6 +166,7 @@ const mockAdHocRunSO: SavedObject = { schedule: { interval: '12h', }, + actions: [], createdBy: 'user', updatedBy: 'user', createdAt: '2019-02-12T21:01:22.479Z', @@ -222,10 +194,41 @@ const mockAdHocRunSO: SavedObject = { describe('findBackfill()', () => { let rulesClient: RulesClient; + let isSystemAction: jest.Mock; beforeEach(async () => { jest.resetAllMocks(); - rulesClient = new RulesClient(rulesClientParams); + isSystemAction = jest.fn().mockReturnValue(false); + mockActionsClient.isSystemAction.mockImplementation(isSystemAction); + + rulesClient = new RulesClient({ + taskManager, + ruleTypeRegistry, + unsecuredSavedObjectsClient, + authorization: authorization as unknown as AlertingAuthorization, + actionsAuthorization: actionsAuthorization as unknown as ActionsAuthorization, + spaceId: 'default', + namespace: 'default', + getUserName: jest.fn(), + createAPIKey: jest.fn(), + logger: loggingSystemMock.create().get(), + internalSavedObjectsRepository, + encryptedSavedObjectsClient: encryptedSavedObjects, + getActionsClient: jest.fn().mockResolvedValue(mockActionsClient), + getEventLogClient: jest.fn(), + kibanaVersion, + auditLogger, + maxScheduledPerMinute: 10000, + minimumScheduleInterval: { value: '1m', enforce: false }, + isAuthenticationTypeAPIKey: jest.fn(), + getAuthenticationAPIKey: jest.fn(), + getAlertIndicesAlias: jest.fn(), + alertsService: null, + backfillClient, + isSystemAction: jest.fn(), + connectorAdapterRegistry: new ConnectorAdapterRegistry(), + uiSettings: uiSettingsServiceMock.createStartContract(), + }); authorization.getFindAuthorizationFilter.mockResolvedValue({ filter, ensureRuleTypeIsAuthorized() {}, @@ -282,7 +285,7 @@ describe('findBackfill()', () => { page: 1, perPage: 10, total: 1, - data: [transformAdHocRunToBackfillResult(mockAdHocRunSO)], + data: [transformAdHocRunToBackfillResult({ adHocRunSO: mockAdHocRunSO, isSystemAction })], }); }); @@ -331,7 +334,7 @@ describe('findBackfill()', () => { page: 1, perPage: 10, total: 1, - data: [transformAdHocRunToBackfillResult(mockAdHocRunSO)], + data: [transformAdHocRunToBackfillResult({ adHocRunSO: mockAdHocRunSO, isSystemAction })], }); }); @@ -398,7 +401,7 @@ describe('findBackfill()', () => { page: 1, perPage: 10, total: 1, - data: [transformAdHocRunToBackfillResult(mockAdHocRunSO)], + data: [transformAdHocRunToBackfillResult({ adHocRunSO: mockAdHocRunSO, isSystemAction })], }); }); @@ -465,7 +468,7 @@ describe('findBackfill()', () => { page: 1, perPage: 10, total: 1, - data: [transformAdHocRunToBackfillResult(mockAdHocRunSO)], + data: [transformAdHocRunToBackfillResult({ adHocRunSO: mockAdHocRunSO, isSystemAction })], }); }); @@ -548,7 +551,7 @@ describe('findBackfill()', () => { page: 1, perPage: 10, total: 1, - data: [transformAdHocRunToBackfillResult(mockAdHocRunSO)], + data: [transformAdHocRunToBackfillResult({ adHocRunSO: mockAdHocRunSO, isSystemAction })], }); }); @@ -633,7 +636,127 @@ describe('findBackfill()', () => { page: 1, perPage: 10, total: 1, - data: [transformAdHocRunToBackfillResult(mockAdHocRunSO)], + data: [transformAdHocRunToBackfillResult({ adHocRunSO: mockAdHocRunSO, isSystemAction })], + }); + }); + + test('should successfully find backfill for rule with actions', async () => { + const mockAdHocRunSOWithActions = { + ...mockAdHocRunSO, + attributes: { + ...mockAdHocRunSO.attributes, + rule: { + ...mockAdHocRunSO.attributes.rule, + actions: [ + { + uuid: '123abc', + group: 'default', + actionRef: 'action_0', + actionTypeId: 'test', + params: {}, + }, + ], + }, + }, + references: [ + { id: 'abc', name: 'rule', type: RULE_SAVED_OBJECT_TYPE }, + { id: '4', name: 'action_0', type: 'action' }, + ], + score: 0, + }; + unsecuredSavedObjectsClient.find.mockResolvedValue({ + saved_objects: [mockAdHocRunSOWithActions], + per_page: 10, + page: 1, + total: 1, + }); + + const result = await rulesClient.findBackfill({ + page: 1, + perPage: 10, + start: '2024-02-09T02:07:55Z', + end: '2024-03-29T02:07:55Z', + ruleIds: 'abc', + }); + + expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith({ + authorizationEntity: 'rule', + filterOpts: { + fieldNames: { + consumer: 'ad_hoc_run_params.attributes.rule.consumer', + ruleTypeId: 'ad_hoc_run_params.attributes.rule.alertTypeId', + }, + type: 'kql', + }, + }); + + expect(unsecuredSavedObjectsClient.find).toHaveBeenCalledWith({ + filter: { + type: 'function', + function: 'and', + arguments: [ + { + type: 'function', + function: 'and', + arguments: [ + { + type: 'function', + function: 'range', + arguments: [ + { isQuoted: false, type: 'literal', value: 'ad_hoc_run_params.attributes.start' }, + 'gte', + { isQuoted: true, type: 'literal', value: '2024-02-09T02:07:55Z' }, + ], + }, + { + type: 'function', + function: 'range', + arguments: [ + { isQuoted: false, type: 'literal', value: 'ad_hoc_run_params.attributes.end' }, + 'lte', + { isQuoted: true, type: 'literal', value: '2024-03-29T02:07:55Z' }, + ], + }, + ], + }, + authDslFilter, + ], + }, + hasReference: [{ id: 'abc', type: RULE_SAVED_OBJECT_TYPE }], + page: 1, + perPage: 10, + type: AD_HOC_RUN_SAVED_OBJECT_TYPE, + }); + + expect(auditLogger.log).toHaveBeenCalledTimes(1); + expect(auditLogger.log).toHaveBeenNthCalledWith(1, { + event: { + action: 'ad_hoc_run_find', + category: ['database'], + outcome: 'success', + type: ['access'], + }, + kibana: { + saved_object: { + id: '1', + type: AD_HOC_RUN_SAVED_OBJECT_TYPE, + name: 'backfill for rule "fakeRuleName"', + }, + }, + message: + 'User has found ad hoc run for ad_hoc_run_params [id=1] backfill for rule "fakeRuleName"', + }); + + expect(result).toEqual({ + page: 1, + perPage: 10, + total: 1, + data: [ + transformAdHocRunToBackfillResult({ + adHocRunSO: mockAdHocRunSOWithActions, + isSystemAction, + }), + ], }); }); @@ -688,7 +811,7 @@ describe('findBackfill()', () => { page: 1, perPage: 10, total: 1, - data: [transformAdHocRunToBackfillResult(mockAdHocRunSO)], + data: [transformAdHocRunToBackfillResult({ adHocRunSO: mockAdHocRunSO, isSystemAction })], }); }); diff --git a/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/find/find_backfill.ts b/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/find/find_backfill.ts index 3482d854bda1f..d6f723d31b06d 100644 --- a/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/find/find_backfill.ts +++ b/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/find/find_backfill.ts @@ -98,6 +98,8 @@ export async function findBackfill( ...(params.sortOrder ? { sortOrder: params.sortOrder } : {}), }); + const actionsClient = await context.getActionsClient(); + const transformedData: Backfill[] = data.map((so: SavedObject) => { context.auditLogger?.log( adHocRunAuditEvent({ @@ -110,7 +112,10 @@ export async function findBackfill( }) ); - return transformAdHocRunToBackfillResult(so) as Backfill; + return transformAdHocRunToBackfillResult({ + adHocRunSO: so, + isSystemAction: (id: string) => actionsClient.isSystemAction(id), + }) as Backfill; }); return { diff --git a/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/get/get_backfill.test.ts b/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/get/get_backfill.test.ts index cbf516bfd446e..7ed0db8a0a9fd 100644 --- a/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/get/get_backfill.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/get/get_backfill.test.ts @@ -6,7 +6,7 @@ */ import { ActionsAuthorization } from '@kbn/actions-plugin/server'; -import { actionsAuthorizationMock } from '@kbn/actions-plugin/server/mocks'; +import { actionsAuthorizationMock, actionsClientMock } from '@kbn/actions-plugin/server/mocks'; import { RULE_SAVED_OBJECT_TYPE } from '../../../..'; import { AlertingAuthorization } from '../../../../authorization'; import { alertingAuthorizationMock } from '../../../../authorization/alerting_authorization.mock'; @@ -21,7 +21,7 @@ import { uiSettingsServiceMock } from '@kbn/core-ui-settings-server-mocks'; import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; import { taskManagerMock } from '@kbn/task-manager-plugin/server/mocks'; -import { ConstructorOptions, RulesClient } from '../../../../rules_client'; +import { RulesClient } from '../../../../rules_client'; import { adHocRunStatus } from '../../../../../common/constants'; import { ConnectorAdapterRegistry } from '../../../../connector_adapters/connector_adapter_registry'; import { AD_HOC_RUN_SAVED_OBJECT_TYPE } from '../../../../saved_objects'; @@ -41,37 +41,9 @@ const internalSavedObjectsRepository = savedObjectsRepositoryMock.create(); const backfillClient = backfillClientMock.create(); const logger = loggingSystemMock.create().get(); -const rulesClientParams: jest.Mocked = { - taskManager, - ruleTypeRegistry, - unsecuredSavedObjectsClient, - authorization: authorization as unknown as AlertingAuthorization, - actionsAuthorization: actionsAuthorization as unknown as ActionsAuthorization, - spaceId: 'default', - namespace: 'default', - getUserName: jest.fn(), - createAPIKey: jest.fn(), - logger, - internalSavedObjectsRepository, - encryptedSavedObjectsClient: encryptedSavedObjects, - getActionsClient: jest.fn(), - getEventLogClient: jest.fn(), - kibanaVersion, - auditLogger, - maxScheduledPerMinute: 10000, - minimumScheduleInterval: { value: '1m', enforce: false }, - isAuthenticationTypeAPIKey: jest.fn(), - getAuthenticationAPIKey: jest.fn(), - getAlertIndicesAlias: jest.fn(), - alertsService: null, - backfillClient, - isSystemAction: jest.fn(), - connectorAdapterRegistry: new ConnectorAdapterRegistry(), - uiSettings: uiSettingsServiceMock.createStartContract(), -}; - const fakeRuleName = 'fakeRuleName'; +const mockActionsClient = actionsClientMock.create(); const mockAdHocRunSO: SavedObject = { id: '1', type: AD_HOC_RUN_SAVED_OBJECT_TYPE, @@ -85,7 +57,7 @@ const mockAdHocRunSO: SavedObject = { name: fakeRuleName, tags: ['foo'], alertTypeId: 'myType', - // @ts-expect-error + actions: [], params: {}, apiKeyOwner: 'user', apiKeyCreatedByUser: false, @@ -121,10 +93,41 @@ const mockAdHocRunSO: SavedObject = { describe('getBackfill()', () => { let rulesClient: RulesClient; + let isSystemAction: jest.Mock; beforeEach(async () => { jest.resetAllMocks(); - rulesClient = new RulesClient(rulesClientParams); + isSystemAction = jest.fn().mockReturnValue(false); + mockActionsClient.isSystemAction.mockImplementation(isSystemAction); + + rulesClient = new RulesClient({ + taskManager, + ruleTypeRegistry, + unsecuredSavedObjectsClient, + authorization: authorization as unknown as AlertingAuthorization, + actionsAuthorization: actionsAuthorization as unknown as ActionsAuthorization, + spaceId: 'default', + namespace: 'default', + getUserName: jest.fn(), + createAPIKey: jest.fn(), + logger, + internalSavedObjectsRepository, + encryptedSavedObjectsClient: encryptedSavedObjects, + getActionsClient: jest.fn().mockResolvedValue(mockActionsClient), + getEventLogClient: jest.fn(), + kibanaVersion, + auditLogger, + maxScheduledPerMinute: 10000, + minimumScheduleInterval: { value: '1m', enforce: false }, + isAuthenticationTypeAPIKey: jest.fn(), + getAuthenticationAPIKey: jest.fn(), + getAlertIndicesAlias: jest.fn(), + alertsService: null, + backfillClient, + isSystemAction: jest.fn(), + connectorAdapterRegistry: new ConnectorAdapterRegistry(), + uiSettings: uiSettingsServiceMock.createStartContract(), + }); unsecuredSavedObjectsClient.get.mockResolvedValue(mockAdHocRunSO); }); @@ -158,7 +161,67 @@ describe('getBackfill()', () => { }); expect(logger.error).not.toHaveBeenCalled(); - expect(result).toEqual(transformAdHocRunToBackfillResult(mockAdHocRunSO)); + expect(result).toEqual( + transformAdHocRunToBackfillResult({ adHocRunSO: mockAdHocRunSO, isSystemAction }) + ); + }); + + test('should successfully get backfill with actions', async () => { + const mockAdHocRunSOWithActions = { + ...mockAdHocRunSO, + attributes: { + ...mockAdHocRunSO.attributes, + rule: { + ...mockAdHocRunSO.attributes.rule, + actions: [ + { + uuid: '123abc', + group: 'default', + actionRef: 'action_0', + actionTypeId: 'test', + params: {}, + }, + ], + }, + }, + references: [ + { id: 'abc', name: 'rule', type: RULE_SAVED_OBJECT_TYPE }, + { id: '4', name: 'action_0', type: 'action' }, + ], + }; + unsecuredSavedObjectsClient.get.mockResolvedValue(mockAdHocRunSOWithActions); + const result = await rulesClient.getBackfill('1'); + + expect(unsecuredSavedObjectsClient.get).toHaveBeenCalledWith(AD_HOC_RUN_SAVED_OBJECT_TYPE, '1'); + expect(authorization.ensureAuthorized).toHaveBeenCalledWith({ + entity: 'rule', + consumer: 'myApp', + operation: 'getBackfill', + ruleTypeId: 'myType', + }); + expect(auditLogger.log).toHaveBeenCalledTimes(1); + expect(auditLogger.log).toHaveBeenCalledWith({ + event: { + action: 'ad_hoc_run_get', + category: ['database'], + outcome: 'success', + type: ['access'], + }, + kibana: { + saved_object: { + id: '1', + type: AD_HOC_RUN_SAVED_OBJECT_TYPE, + name: `backfill for rule "fakeRuleName"`, + }, + }, + message: + 'User has got ad hoc run for ad_hoc_run_params [id=1] backfill for rule "fakeRuleName"', + }); + expect(logger.error).not.toHaveBeenCalled(); + + expect(result).toEqual( + transformAdHocRunToBackfillResult({ adHocRunSO: mockAdHocRunSOWithActions, isSystemAction }) + ); }); describe('error handling', () => { diff --git a/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/get/get_backfill.ts b/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/get/get_backfill.ts index 6f14dba88684c..4bd2ff3a5d4b3 100644 --- a/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/get/get_backfill.ts +++ b/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/get/get_backfill.ts @@ -73,7 +73,11 @@ export async function getBackfill(context: RulesClientContext, id: string): Prom }) ); - return transformAdHocRunToBackfillResult(result) as Backfill; + const actionsClient = await context.getActionsClient(); + return transformAdHocRunToBackfillResult({ + adHocRunSO: result, + isSystemAction: (connectorId: string) => actionsClient.isSystemAction(connectorId), + }) as Backfill; } catch (err) { const errorMessage = `Failed to get backfill by id: ${id}`; context.logger.error(`${errorMessage} - ${err}`); diff --git a/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/schedule/schedule_backfill.test.ts b/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/schedule/schedule_backfill.test.ts index a0a79421c7358..25df7048d4b44 100644 --- a/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/schedule/schedule_backfill.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/schedule/schedule_backfill.test.ts @@ -180,6 +180,7 @@ function getMockData(overwrites: Record = {}): ScheduleBackfill return { ruleId: '1', start: '2023-11-16T08:00:00.000Z', + runActions: true, ...overwrites, }; } @@ -481,13 +482,13 @@ describe('scheduleBackfill()', () => { // @ts-expect-error rulesClient.scheduleBackfill(getMockData()) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Error validating backfill schedule parameters \\"{\\"ruleId\\":\\"1\\",\\"start\\":\\"2023-11-16T08:00:00.000Z\\"}\\" - expected value of type [array] but got [Object]"` + `"Error validating backfill schedule parameters \\"{\\"ruleId\\":\\"1\\",\\"start\\":\\"2023-11-16T08:00:00.000Z\\",\\"runActions\\":true}\\" - expected value of type [array] but got [Object]"` ); await expect( rulesClient.scheduleBackfill([getMockData({ ruleId: 1 })]) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Error validating backfill schedule parameters \\"[{\\"ruleId\\":1,\\"start\\":\\"2023-11-16T08:00:00.000Z\\"}]\\" - [0.ruleId]: expected value of type [string] but got [number]"` + `"Error validating backfill schedule parameters \\"[{\\"ruleId\\":1,\\"start\\":\\"2023-11-16T08:00:00.000Z\\",\\"runActions\\":true}]\\" - [0.ruleId]: expected value of type [string] but got [number]"` ); }); @@ -502,7 +503,7 @@ describe('scheduleBackfill()', () => { }), ]) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Error validating backfill schedule parameters \\"[{\\"ruleId\\":\\"1\\",\\"start\\":\\"2023-11-16T08:00:00.000Z\\"},{\\"ruleId\\":\\"2\\",\\"start\\":\\"2023-11-17T08:00:00.000Z\\",\\"end\\":\\"2023-11-17T08:00:00.000Z\\"}]\\" - [1]: Backfill end must be greater than backfill start"` + `"Error validating backfill schedule parameters \\"[{\\"ruleId\\":\\"1\\",\\"start\\":\\"2023-11-16T08:00:00.000Z\\",\\"runActions\\":true},{\\"ruleId\\":\\"2\\",\\"start\\":\\"2023-11-17T08:00:00.000Z\\",\\"runActions\\":true,\\"end\\":\\"2023-11-17T08:00:00.000Z\\"}]\\" - [1]: Backfill end must be greater than backfill start"` ); await expect( @@ -515,7 +516,7 @@ describe('scheduleBackfill()', () => { }), ]) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Error validating backfill schedule parameters \\"[{\\"ruleId\\":\\"1\\",\\"start\\":\\"2023-11-16T08:00:00.000Z\\"},{\\"ruleId\\":\\"2\\",\\"start\\":\\"2023-11-17T08:00:00.000Z\\",\\"end\\":\\"2023-11-16T08:00:00.000Z\\"}]\\" - [1]: Backfill end must be greater than backfill start"` + `"Error validating backfill schedule parameters \\"[{\\"ruleId\\":\\"1\\",\\"start\\":\\"2023-11-16T08:00:00.000Z\\",\\"runActions\\":true},{\\"ruleId\\":\\"2\\",\\"start\\":\\"2023-11-17T08:00:00.000Z\\",\\"runActions\\":true,\\"end\\":\\"2023-11-16T08:00:00.000Z\\"}]\\" - [1]: Backfill end must be greater than backfill start"` ); }); diff --git a/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/schedule/schedule_backfill.ts b/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/schedule/schedule_backfill.ts index 2dec1a78e3171..5d2dd5f56a92e 100644 --- a/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/schedule/schedule_backfill.ts +++ b/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/schedule/schedule_backfill.ts @@ -145,6 +145,7 @@ export async function scheduleBackfill( const actionsClient = await context.getActionsClient(); return await context.backfillClient.bulkQueue({ + actionsClient, auditLogger: context.auditLogger, params, rules: rulesToSchedule.map(({ id, attributes, references }) => { diff --git a/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/schedule/schemas/schedule_backfill_params_schema.ts b/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/schedule/schemas/schedule_backfill_params_schema.ts index c4a469da1b5db..ce1d14b7400af 100644 --- a/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/schedule/schemas/schedule_backfill_params_schema.ts +++ b/x-pack/platform/plugins/shared/alerting/server/application/backfill/methods/schedule/schemas/schedule_backfill_params_schema.ts @@ -14,6 +14,7 @@ export const scheduleBackfillParamSchema = schema.object( ruleId: schema.string(), start: schema.string(), end: schema.maybe(schema.string()), + runActions: schema.maybe(schema.boolean()), }, { validate({ start, end }) { diff --git a/x-pack/platform/plugins/shared/alerting/server/application/backfill/result/schemas/index.ts b/x-pack/platform/plugins/shared/alerting/server/application/backfill/result/schemas/index.ts index b454d41dd40ca..ecba6cc45ae1c 100644 --- a/x-pack/platform/plugins/shared/alerting/server/application/backfill/result/schemas/index.ts +++ b/x-pack/platform/plugins/shared/alerting/server/application/backfill/result/schemas/index.ts @@ -8,6 +8,7 @@ import { schema } from '@kbn/config-schema'; import { ruleParamsSchema } from '@kbn/response-ops-rule-params'; import { adHocRunStatus } from '../../../../../common/constants'; +import { actionSchema as ruleActionSchema } from '../../../rule/schemas/action_schemas'; export const statusSchema = schema.oneOf([ schema.literal(adHocRunStatus.COMPLETE), @@ -32,6 +33,7 @@ export const backfillSchema = schema.object({ id: schema.string(), name: schema.string(), tags: schema.arrayOf(schema.string()), + actions: schema.arrayOf(ruleActionSchema), alertTypeId: schema.string(), params: ruleParamsSchema, apiKeyOwner: schema.nullable(schema.string()), @@ -50,4 +52,5 @@ export const backfillSchema = schema.object({ status: statusSchema, end: schema.maybe(schema.string()), schedule: schema.arrayOf(backfillScheduleSchema), + warnings: schema.maybe(schema.arrayOf(schema.string())), }); diff --git a/x-pack/platform/plugins/shared/alerting/server/application/backfill/transforms/transform_ad_hoc_run_to_backfill_result.test.ts b/x-pack/platform/plugins/shared/alerting/server/application/backfill/transforms/transform_ad_hoc_run_to_backfill_result.test.ts index 995240cbbd023..2d0e6ff20da08 100644 --- a/x-pack/platform/plugins/shared/alerting/server/application/backfill/transforms/transform_ad_hoc_run_to_backfill_result.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/application/backfill/transforms/transform_ad_hoc_run_to_backfill_result.test.ts @@ -8,17 +8,24 @@ import { AdHocRunSO } from '../../../data/ad_hoc_run/types'; import { SavedObject } from '@kbn/core/server'; import { adHocRunStatus } from '../../../../common/constants'; -import { transformAdHocRunToBackfillResult } from './transform_ad_hoc_run_to_backfill_result'; +import { + transformAdHocRunToAdHocRunData, + transformAdHocRunToBackfillResult, +} from './transform_ad_hoc_run_to_backfill_result'; +import { RawRule } from '../../../types'; + +const isSystemAction = jest.fn().mockReturnValue(false); function getMockAdHocRunAttributes({ ruleId, - overwrites, omitApiKey = false, + actions, }: { ruleId?: string; - overwrites?: Record; omitApiKey?: boolean; + actions?: RawRule['actions']; } = {}): AdHocRunSO { + // @ts-expect-error return { ...(omitApiKey ? {} : { apiKeyId: '123', apiKeyToUse: 'MTIzOmFiYw==' }), createdAt: '2024-01-30T00:00:00.000Z', @@ -29,7 +36,7 @@ function getMockAdHocRunAttributes({ name: 'my rule name', tags: ['foo'], alertTypeId: 'myType', - // @ts-expect-error + actions: actions ? actions : [], params: {}, apiKeyOwner: 'user', apiKeyCreatedByUser: false, @@ -59,14 +66,14 @@ function getMockAdHocRunAttributes({ runAt: '2023-10-20T15:07:40.011Z', }, ], - ...overwrites, }; } function getBulkCreateResponse( id: string, ruleId: string, - attributes: AdHocRunSO + attributes: AdHocRunSO, + additionalReferences?: Array<{ id: string; name: string; type: string }> ): SavedObject { return { type: 'ad_hoc_rule_run_params', @@ -79,6 +86,7 @@ function getBulkCreateResponse( name: 'rule', type: 'alert', }, + ...(additionalReferences ?? []), ], managed: false, coreMigrationVersion: '8.8.0', @@ -91,9 +99,74 @@ function getBulkCreateResponse( describe('transformAdHocRunToBackfillResult', () => { test('should transform bulk create response', () => { expect( - transformAdHocRunToBackfillResult( - getBulkCreateResponse('abc', '1', getMockAdHocRunAttributes()) - ) + transformAdHocRunToBackfillResult({ + adHocRunSO: getBulkCreateResponse('abc', '1', getMockAdHocRunAttributes()), + isSystemAction, + }) + ).toEqual({ + id: 'abc', + createdAt: '2024-01-30T00:00:00.000Z', + duration: '12h', + enabled: true, + rule: { + id: '1', + name: 'my rule name', + tags: ['foo'], + actions: [], + alertTypeId: 'myType', + params: {}, + apiKeyOwner: 'user', + apiKeyCreatedByUser: false, + consumer: 'myApp', + enabled: true, + schedule: { + interval: '12h', + }, + createdBy: 'user', + updatedBy: 'user', + createdAt: '2019-02-12T21:01:22.479Z', + updatedAt: '2019-02-12T21:01:22.479Z', + revision: 0, + }, + spaceId: 'default', + start: '2023-10-19T15:07:40.011Z', + status: adHocRunStatus.PENDING, + schedule: [ + { + interval: '12h', + status: adHocRunStatus.PENDING, + runAt: '2023-10-20T03:07:40.011Z', + }, + { + interval: '12h', + status: adHocRunStatus.PENDING, + runAt: '2023-10-20T15:07:40.011Z', + }, + ], + }); + }); + + test('should transform bulk create response with actions', () => { + expect( + transformAdHocRunToBackfillResult({ + adHocRunSO: getBulkCreateResponse( + 'abc', + '1', + getMockAdHocRunAttributes({ + actions: [ + { + uuid: '123abc', + group: 'default', + actionRef: 'action_0', + actionTypeId: 'test', + params: {}, + }, + ], + }), + [{ id: '4', name: 'action_0', type: 'action' }] + ), + isSystemAction, + }) ).toEqual({ id: 'abc', createdAt: '2024-01-30T00:00:00.000Z', @@ -103,6 +176,7 @@ describe('transformAdHocRunToBackfillResult', () => { id: '1', name: 'my rule name', tags: ['foo'], + actions: [{ actionTypeId: 'test', group: 'default', id: '4', params: {}, uuid: '123abc' }], alertTypeId: 'myType', params: {}, apiKeyOwner: 'user', @@ -138,10 +212,10 @@ describe('transformAdHocRunToBackfillResult', () => { test('should return error for malformed responses when original create request is not provided', () => { expect( - transformAdHocRunToBackfillResult( + transformAdHocRunToBackfillResult({ // missing id // @ts-expect-error - { + adHocRunSO: { type: 'ad_hoc_rule_run_params', namespaces: ['default'], attributes: getMockAdHocRunAttributes(), @@ -151,8 +225,9 @@ describe('transformAdHocRunToBackfillResult', () => { updated_at: '2024-02-07T16:05:39.296Z', created_at: '2024-02-07T16:05:39.296Z', version: 'WzcsMV0=', - } - ) + }, + isSystemAction, + }) ).toEqual({ error: { message: 'Malformed saved object in bulkCreate response - Missing "id".', @@ -160,10 +235,10 @@ describe('transformAdHocRunToBackfillResult', () => { }, }); expect( - transformAdHocRunToBackfillResult( + transformAdHocRunToBackfillResult({ // missing attributes // @ts-expect-error - { + adHocRunSO: { type: 'ad_hoc_rule_run_params', id: 'abc', namespaces: ['default'], @@ -173,8 +248,9 @@ describe('transformAdHocRunToBackfillResult', () => { updated_at: '2024-02-07T16:05:39.296Z', created_at: '2024-02-07T16:05:39.296Z', version: 'WzcsMV0=', - } - ) + }, + isSystemAction, + }) ).toEqual({ error: { message: 'Malformed saved object in bulkCreate response - Missing "attributes".', @@ -182,10 +258,10 @@ describe('transformAdHocRunToBackfillResult', () => { }, }); expect( - transformAdHocRunToBackfillResult( + transformAdHocRunToBackfillResult({ // missing references // @ts-expect-error - { + adHocRunSO: { type: 'ad_hoc_rule_run_params', id: 'def', namespaces: ['default'], @@ -195,8 +271,9 @@ describe('transformAdHocRunToBackfillResult', () => { updated_at: '2024-02-07T16:05:39.296Z', created_at: '2024-02-07T16:05:39.296Z', version: 'WzcsMV0=', - } - ) + }, + isSystemAction, + }) ).toEqual({ error: { message: 'Malformed saved object in bulkCreate response - Missing "references".', @@ -204,9 +281,9 @@ describe('transformAdHocRunToBackfillResult', () => { }, }); expect( - transformAdHocRunToBackfillResult( + transformAdHocRunToBackfillResult({ // empty references - { + adHocRunSO: { type: 'ad_hoc_rule_run_params', id: 'ghi', namespaces: ['default'], @@ -217,8 +294,9 @@ describe('transformAdHocRunToBackfillResult', () => { updated_at: '2024-02-07T16:05:39.296Z', created_at: '2024-02-07T16:05:39.296Z', version: 'WzcsMV0=', - } - ) + }, + isSystemAction, + }) ).toEqual({ error: { message: 'Malformed saved object in bulkCreate response - Missing "references".', @@ -230,10 +308,10 @@ describe('transformAdHocRunToBackfillResult', () => { test('should return error for malformed responses when original create request is provided', () => { const attributes = getMockAdHocRunAttributes(); expect( - transformAdHocRunToBackfillResult( + transformAdHocRunToBackfillResult({ // missing id // @ts-expect-error - { + adHocRunSO: { type: 'ad_hoc_rule_run_params', namespaces: ['default'], attributes, @@ -244,12 +322,13 @@ describe('transformAdHocRunToBackfillResult', () => { created_at: '2024-02-07T16:05:39.296Z', version: 'WzcsMV0=', }, - { + originalSO: { type: 'ad_hoc_rule_run_params', attributes, references: [{ id: '1', name: 'rule', type: 'alert' }], - } - ) + }, + isSystemAction, + }) ).toEqual({ error: { message: 'Malformed saved object in bulkCreate response - Missing "id".', @@ -257,10 +336,10 @@ describe('transformAdHocRunToBackfillResult', () => { }, }); expect( - transformAdHocRunToBackfillResult( + transformAdHocRunToBackfillResult({ // missing attributes // @ts-expect-error - { + adHocRunSO: { type: 'ad_hoc_rule_run_params', id: 'abc', namespaces: ['default'], @@ -271,12 +350,13 @@ describe('transformAdHocRunToBackfillResult', () => { created_at: '2024-02-07T16:05:39.296Z', version: 'WzcsMV0=', }, - { + originalSO: { type: 'ad_hoc_rule_run_params', attributes, references: [{ id: '1', name: 'rule', type: 'alert' }], - } - ) + }, + isSystemAction, + }) ).toEqual({ error: { message: 'Malformed saved object in bulkCreate response - Missing "attributes".', @@ -284,10 +364,10 @@ describe('transformAdHocRunToBackfillResult', () => { }, }); expect( - transformAdHocRunToBackfillResult( + transformAdHocRunToBackfillResult({ // missing references // @ts-expect-error - { + adHocRunSO: { type: 'ad_hoc_rule_run_params', id: 'def', namespaces: ['default'], @@ -298,12 +378,13 @@ describe('transformAdHocRunToBackfillResult', () => { created_at: '2024-02-07T16:05:39.296Z', version: 'WzcsMV0=', }, - { + originalSO: { type: 'ad_hoc_rule_run_params', attributes, references: [{ id: '1', name: 'rule', type: 'alert' }], - } - ) + }, + isSystemAction, + }) ).toEqual({ error: { message: 'Malformed saved object in bulkCreate response - Missing "references".', @@ -311,9 +392,9 @@ describe('transformAdHocRunToBackfillResult', () => { }, }); expect( - transformAdHocRunToBackfillResult( + transformAdHocRunToBackfillResult({ // empty references - { + adHocRunSO: { type: 'ad_hoc_rule_run_params', id: 'ghi', namespaces: ['default'], @@ -325,12 +406,13 @@ describe('transformAdHocRunToBackfillResult', () => { created_at: '2024-02-07T16:05:39.296Z', version: 'WzcsMV0=', }, - { + originalSO: { type: 'ad_hoc_rule_run_params', attributes, references: [{ id: '1', name: 'rule', type: 'alert' }], - } - ) + }, + isSystemAction, + }) ).toEqual({ error: { message: 'Malformed saved object in bulkCreate response - Missing "references".', @@ -341,9 +423,9 @@ describe('transformAdHocRunToBackfillResult', () => { test('should pass through error if saved object error when original create request is not provided', () => { expect( - transformAdHocRunToBackfillResult( + transformAdHocRunToBackfillResult({ // @ts-expect-error - { + adHocRunSO: { type: 'ad_hoc_rule_run_params', id: '788a2784-c021-484f-a53e-0c1c63c7567c', error: { @@ -351,8 +433,9 @@ describe('transformAdHocRunToBackfillResult', () => { message: 'Unable to create', statusCode: 404, }, - } - ) + }, + isSystemAction, + }) ).toEqual({ error: { message: 'Unable to create', @@ -363,9 +446,9 @@ describe('transformAdHocRunToBackfillResult', () => { test('should pass through error if saved object error when original create request is provided', () => { expect( - transformAdHocRunToBackfillResult( + transformAdHocRunToBackfillResult({ // @ts-expect-error - { + adHocRunSO: { type: 'ad_hoc_rule_run_params', id: '788a2784-c021-484f-a53e-0c1c63c7567c', error: { @@ -374,12 +457,13 @@ describe('transformAdHocRunToBackfillResult', () => { statusCode: 404, }, }, - { + originalSO: { type: 'ad_hoc_rule_run_params', attributes: getMockAdHocRunAttributes(), references: [{ id: '1', name: 'rule', type: 'alert' }], - } - ) + }, + isSystemAction, + }) ).toEqual({ error: { message: 'Unable to create', @@ -388,3 +472,122 @@ describe('transformAdHocRunToBackfillResult', () => { }); }); }); + +describe('transformAdHocRunToAdHocRunData', () => { + test('should transform bulk create response and include api key', () => { + expect( + transformAdHocRunToAdHocRunData({ + adHocRunSO: getBulkCreateResponse('abc', '1', getMockAdHocRunAttributes()), + isSystemAction, + }) + ).toEqual({ + id: 'abc', + apiKeyId: '123', + apiKeyToUse: 'MTIzOmFiYw==', + createdAt: '2024-01-30T00:00:00.000Z', + duration: '12h', + enabled: true, + rule: { + id: '1', + name: 'my rule name', + tags: ['foo'], + actions: [], + alertTypeId: 'myType', + params: {}, + apiKeyOwner: 'user', + apiKeyCreatedByUser: false, + consumer: 'myApp', + enabled: true, + schedule: { + interval: '12h', + }, + createdBy: 'user', + updatedBy: 'user', + createdAt: '2019-02-12T21:01:22.479Z', + updatedAt: '2019-02-12T21:01:22.479Z', + revision: 0, + }, + spaceId: 'default', + start: '2023-10-19T15:07:40.011Z', + status: adHocRunStatus.PENDING, + schedule: [ + { + interval: '12h', + status: adHocRunStatus.PENDING, + runAt: '2023-10-20T03:07:40.011Z', + }, + { + interval: '12h', + status: adHocRunStatus.PENDING, + runAt: '2023-10-20T15:07:40.011Z', + }, + ], + }); + }); + + test('should transform bulk create response with actions and include api key', () => { + expect( + transformAdHocRunToAdHocRunData({ + adHocRunSO: getBulkCreateResponse( + 'abc', + '1', + getMockAdHocRunAttributes({ + actions: [ + { + uuid: '123abc', + group: 'default', + actionRef: 'action_0', + actionTypeId: 'test', + params: {}, + }, + ], + }), + [{ id: '4', name: 'action_0', type: 'action' }] + ), + isSystemAction, + }) + ).toEqual({ + id: 'abc', + apiKeyId: '123', + apiKeyToUse: 'MTIzOmFiYw==', + createdAt: '2024-01-30T00:00:00.000Z', + duration: '12h', + enabled: true, + rule: { + id: '1', + name: 'my rule name', + tags: ['foo'], + actions: [{ actionTypeId: 'test', group: 'default', id: '4', params: {}, uuid: '123abc' }], + alertTypeId: 'myType', + params: {}, + apiKeyOwner: 'user', + apiKeyCreatedByUser: false, + consumer: 'myApp', + enabled: true, + schedule: { + interval: '12h', + }, + createdBy: 'user', + updatedBy: 'user', + createdAt: '2019-02-12T21:01:22.479Z', + updatedAt: '2019-02-12T21:01:22.479Z', + revision: 0, + }, + spaceId: 'default', + start: '2023-10-19T15:07:40.011Z', + status: adHocRunStatus.PENDING, + schedule: [ + { + interval: '12h', + status: adHocRunStatus.PENDING, + runAt: '2023-10-20T03:07:40.011Z', + }, + { + interval: '12h', + status: adHocRunStatus.PENDING, + runAt: '2023-10-20T15:07:40.011Z', + }, + ], + }); + }); +}); diff --git a/x-pack/platform/plugins/shared/alerting/server/application/backfill/transforms/transform_ad_hoc_run_to_backfill_result.ts b/x-pack/platform/plugins/shared/alerting/server/application/backfill/transforms/transform_ad_hoc_run_to_backfill_result.ts index 13257742b7005..78b228711df7d 100644 --- a/x-pack/platform/plugins/shared/alerting/server/application/backfill/transforms/transform_ad_hoc_run_to_backfill_result.ts +++ b/x-pack/platform/plugins/shared/alerting/server/application/backfill/transforms/transform_ad_hoc_run_to_backfill_result.ts @@ -6,14 +6,25 @@ */ import { SavedObject, SavedObjectsBulkCreateObject } from '@kbn/core/server'; -import { AdHocRunSO } from '../../../data/ad_hoc_run/types'; +import { AdHocRun, AdHocRunSO } from '../../../data/ad_hoc_run/types'; import { createBackfillError } from '../../../backfill_client/lib'; import { ScheduleBackfillResult } from '../methods/schedule/types'; +import { transformRawActionsToDomainActions } from '../../rule/transforms'; -export const transformAdHocRunToBackfillResult = ( - { id, attributes, references, error }: SavedObject, - originalSO?: SavedObjectsBulkCreateObject -): ScheduleBackfillResult => { +interface TransformAdHocRunToBackfillResultOpts { + adHocRunSO: SavedObject; + isSystemAction: (connectorId: string) => boolean; + originalSO?: SavedObjectsBulkCreateObject; + omitGeneratedActionValues?: boolean; +} + +export const transformAdHocRunToBackfillResult = ({ + adHocRunSO, + isSystemAction, + originalSO, + omitGeneratedActionValues = true, +}: TransformAdHocRunToBackfillResultOpts): ScheduleBackfillResult => { + const { id, attributes, references, error } = adHocRunSO; const ruleId = references?.[0]?.id ?? originalSO?.references?.[0]?.id ?? 'unknown'; const ruleName = attributes?.rule?.name ?? originalSO?.attributes?.rule.name; if (error) { @@ -55,6 +66,13 @@ export const transformAdHocRunToBackfillResult = ( rule: { ...attributes.rule, id: references[0].id, + actions: transformRawActionsToDomainActions({ + ruleId: id, + actions: attributes.rule.actions, + references, + isSystemAction, + omitGeneratedValues: omitGeneratedActionValues, + }), }, spaceId: attributes.spaceId, start: attributes.start, @@ -62,3 +80,24 @@ export const transformAdHocRunToBackfillResult = ( schedule: attributes.schedule, }; }; + +// includes API key information +export const transformAdHocRunToAdHocRunData = ({ + adHocRunSO, + isSystemAction, + originalSO, + omitGeneratedActionValues = true, +}: TransformAdHocRunToBackfillResultOpts): AdHocRun => { + const result = transformAdHocRunToBackfillResult({ + adHocRunSO, + isSystemAction, + originalSO, + omitGeneratedActionValues, + }); + + return { + ...result, + apiKeyId: adHocRunSO.attributes.apiKeyId, + apiKeyToUse: adHocRunSO.attributes.apiKeyToUse, + } as AdHocRun; +}; diff --git a/x-pack/platform/plugins/shared/alerting/server/application/backfill/transforms/transform_backfill_param_to_ad_hoc_run.test.ts b/x-pack/platform/plugins/shared/alerting/server/application/backfill/transforms/transform_backfill_param_to_ad_hoc_run.test.ts index 0dd1995e05b98..822ffed9dfce6 100644 --- a/x-pack/platform/plugins/shared/alerting/server/application/backfill/transforms/transform_backfill_param_to_ad_hoc_run.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/application/backfill/transforms/transform_backfill_param_to_ad_hoc_run.test.ts @@ -14,6 +14,7 @@ function getMockData(overwrites: Record = {}): ScheduleBackfill return { ruleId: '1', start: '2023-11-16T08:00:00.000Z', + runActions: true, ...overwrites, }; } @@ -63,7 +64,7 @@ describe('transformBackfillParamToAdHocRun', () => { }); test('should transform backfill param with start', () => { - expect(transformBackfillParamToAdHocRun(getMockData(), getMockRule(), 'default')).toEqual({ + expect(transformBackfillParamToAdHocRun(getMockData(), getMockRule(), [], 'default')).toEqual({ apiKeyId: '123', apiKeyToUse: 'MTIzOmFiYw==', createdAt: '2024-01-30T00:00:00.000Z', @@ -75,6 +76,7 @@ describe('transformBackfillParamToAdHocRun', () => { name: 'my rule name', tags: ['foo'], alertTypeId: 'myType', + actions: [], params: {}, apiKeyOwner: 'user', apiKeyCreatedByUser: false, @@ -107,6 +109,7 @@ describe('transformBackfillParamToAdHocRun', () => { transformBackfillParamToAdHocRun( getMockData({ end: '2023-11-17T08:00:00.000Z' }), getMockRule(), + [], 'default' ) ).toEqual({ @@ -120,6 +123,7 @@ describe('transformBackfillParamToAdHocRun', () => { name: 'my rule name', tags: ['foo'], alertTypeId: 'myType', + actions: [], params: {}, apiKeyOwner: 'user', apiKeyCreatedByUser: false, @@ -151,4 +155,101 @@ describe('transformBackfillParamToAdHocRun', () => { ], }); }); + + test('should transform backfill param with rule actions', () => { + const actions = [ + { uuid: '123abc', group: 'default', actionRef: 'action_0', actionTypeId: 'test', params: {} }, + ]; + expect( + transformBackfillParamToAdHocRun(getMockData(), getMockRule(), actions, 'default') + ).toEqual({ + apiKeyId: '123', + apiKeyToUse: 'MTIzOmFiYw==', + createdAt: '2024-01-30T00:00:00.000Z', + duration: '12h', + enabled: true, + // injects end parameter + end: '2023-11-16T20:00:00.000Z', + rule: { + name: 'my rule name', + tags: ['foo'], + alertTypeId: 'myType', + actions, + params: {}, + apiKeyOwner: 'user', + apiKeyCreatedByUser: false, + consumer: 'myApp', + enabled: true, + schedule: { + interval: '12h', + }, + createdBy: 'user', + updatedBy: 'user', + createdAt: '2019-02-12T21:01:22.479Z', + updatedAt: '2019-02-12T21:01:22.479Z', + revision: 0, + }, + spaceId: 'default', + start: '2023-11-16T08:00:00.000Z', + status: adHocRunStatus.PENDING, + schedule: [ + { + runAt: '2023-11-16T20:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + ], + }); + }); + + test('should omit rule actions when runActions=false', () => { + const actions = [ + { uuid: '123abc', group: 'default', actionRef: 'action_0', actionTypeId: 'test', params: {} }, + ]; + expect( + transformBackfillParamToAdHocRun( + getMockData({ runActions: false }), + getMockRule(), + actions, + 'default' + ) + ).toEqual({ + apiKeyId: '123', + apiKeyToUse: 'MTIzOmFiYw==', + createdAt: '2024-01-30T00:00:00.000Z', + duration: '12h', + enabled: true, + // injects end parameter + end: '2023-11-16T20:00:00.000Z', + rule: { + name: 'my rule name', + tags: ['foo'], + alertTypeId: 'myType', + actions: [], + params: {}, + apiKeyOwner: 'user', + apiKeyCreatedByUser: false, + consumer: 'myApp', + enabled: true, + schedule: { + interval: '12h', + }, + createdBy: 'user', + updatedBy: 'user', + createdAt: '2019-02-12T21:01:22.479Z', + updatedAt: '2019-02-12T21:01:22.479Z', + revision: 0, + }, + spaceId: 'default', + start: '2023-11-16T08:00:00.000Z', + status: adHocRunStatus.PENDING, + schedule: [ + { + runAt: '2023-11-16T20:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + ], + }); + }); }); diff --git a/x-pack/platform/plugins/shared/alerting/server/application/backfill/transforms/transform_backfill_param_to_ad_hoc_run.ts b/x-pack/platform/plugins/shared/alerting/server/application/backfill/transforms/transform_backfill_param_to_ad_hoc_run.ts index 4dc01a6c8939e..b293f7215fec4 100644 --- a/x-pack/platform/plugins/shared/alerting/server/application/backfill/transforms/transform_backfill_param_to_ad_hoc_run.ts +++ b/x-pack/platform/plugins/shared/alerting/server/application/backfill/transforms/transform_backfill_param_to_ad_hoc_run.ts @@ -6,6 +6,7 @@ */ import { isString } from 'lodash'; +import { DenormalizedAction } from '../../../rules_client'; import { AdHocRunSO } from '../../../data/ad_hoc_run/types'; import { calculateSchedule } from '../../../backfill_client/lib'; import { adHocRunStatus } from '../../../../common/constants'; @@ -15,9 +16,12 @@ import { ScheduleBackfillParam } from '../methods/schedule/types'; export const transformBackfillParamToAdHocRun = ( param: ScheduleBackfillParam, rule: RuleDomain, + actions: DenormalizedAction[], spaceId: string ): AdHocRunSO => { const schedule = calculateSchedule(param.start, rule.schedule.interval, param.end); + const shouldRunActions = param.runActions !== undefined ? param.runActions : true; + return { apiKeyId: Buffer.from(rule.apiKey!, 'base64').toString().split(':')[0], apiKeyToUse: rule.apiKey!, @@ -32,6 +36,7 @@ export const transformBackfillParamToAdHocRun = ( params: rule.params, apiKeyOwner: rule.apiKeyOwner, apiKeyCreatedByUser: rule.apiKeyCreatedByUser, + actions: shouldRunActions ? actions : [], consumer: rule.consumer, enabled: rule.enabled, schedule: rule.schedule, diff --git a/x-pack/platform/plugins/shared/alerting/server/application/rule/methods/aggregate/types/index.ts b/x-pack/platform/plugins/shared/alerting/server/application/rule/methods/aggregate/types/index.ts index e146928efcfff..804ed47227e99 100644 --- a/x-pack/platform/plugins/shared/alerting/server/application/rule/methods/aggregate/types/index.ts +++ b/x-pack/platform/plugins/shared/alerting/server/application/rule/methods/aggregate/types/index.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { AggregationsAggregationContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { AggregationsAggregationContainer } from '@elastic/elasticsearch/lib/api/types'; import { TypeOf } from '@kbn/config-schema'; import { KueryNode } from '@kbn/es-query'; import { aggregateOptionsSchema } from '../schemas'; diff --git a/x-pack/platform/plugins/shared/alerting/server/application/rule/methods/aggregate/validation/validate_rule_aggregation_fields.ts b/x-pack/platform/plugins/shared/alerting/server/application/rule/methods/aggregate/validation/validate_rule_aggregation_fields.ts index 6b61d7aa5c324..df35050455a82 100644 --- a/x-pack/platform/plugins/shared/alerting/server/application/rule/methods/aggregate/validation/validate_rule_aggregation_fields.ts +++ b/x-pack/platform/plugins/shared/alerting/server/application/rule/methods/aggregate/validation/validate_rule_aggregation_fields.ts @@ -6,7 +6,7 @@ */ import Boom from '@hapi/boom'; -import type { AggregationsAggregationContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { AggregationsAggregationContainer } from '@elastic/elasticsearch/lib/api/types'; const ALLOW_FIELDS = [ 'alert.attributes.executionStatus.status', diff --git a/x-pack/platform/plugins/shared/alerting/server/authorization/alerting_authorization_kuery.ts b/x-pack/platform/plugins/shared/alerting/server/authorization/alerting_authorization_kuery.ts index 666059c7a7b47..744c2db2f97a0 100644 --- a/x-pack/platform/plugins/shared/alerting/server/authorization/alerting_authorization_kuery.ts +++ b/x-pack/platform/plugins/shared/alerting/server/authorization/alerting_authorization_kuery.ts @@ -8,7 +8,7 @@ import { remove } from 'lodash'; import { EsQueryConfig, nodeBuilder, toElasticsearchQuery, KueryNode } from '@kbn/es-query'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { AuthorizedRuleTypes } from './alerting_authorization'; export enum AlertingAuthorizationFilterType { diff --git a/x-pack/platform/plugins/shared/alerting/server/backfill_client/backfill_client.test.ts b/x-pack/platform/plugins/shared/alerting/server/backfill_client/backfill_client.test.ts index 771f5a4db34b9..8bfd0be4dff65 100644 --- a/x-pack/platform/plugins/shared/alerting/server/backfill_client/backfill_client.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/backfill_client/backfill_client.test.ts @@ -22,6 +22,8 @@ import { taskManagerMock } from '@kbn/task-manager-plugin/server/mocks'; import { TaskRunnerFactory } from '../task_runner'; import { TaskPriority } from '@kbn/task-manager-plugin/server'; import { UntypedNormalizedRuleType } from '../rule_type_registry'; +import { actionsClientMock } from '@kbn/actions-plugin/server/mocks'; +import { RawRule, RawRuleAction } from '../types'; const logger = loggingSystemMock.create().get(); const taskManagerSetup = taskManagerMock.createSetup(); @@ -29,11 +31,13 @@ const taskManagerStart = taskManagerMock.createStart(); const ruleTypeRegistry = ruleTypeRegistryMock.create(); const unsecuredSavedObjectsClient = savedObjectsClientMock.create(); const auditLogger = auditLoggerMock.create(); +const actionsClient = actionsClientMock.create(); function getMockData(overwrites: Record = {}): ScheduleBackfillParam { return { ruleId: '1', start: '2023-11-16T08:00:00.000Z', + runActions: true, ...overwrites, }; } @@ -98,11 +102,14 @@ function getMockAdHocRunAttributes({ ruleId, overwrites, omitApiKey = false, + actions = [], }: { ruleId?: string; overwrites?: Record; omitApiKey?: boolean; + actions?: RawRule['actions']; } = {}): AdHocRunSO { + // @ts-expect-error return { ...(omitApiKey ? {} : { apiKeyId: '123', apiKeyToUse: 'MTIzOmFiYw==' }), createdAt: '2024-01-30T00:00:00.000Z', @@ -113,7 +120,7 @@ function getMockAdHocRunAttributes({ name: 'my rule name', tags: ['foo'], alertTypeId: 'myType', - // @ts-expect-error + actions, params: {}, apiKeyOwner: 'user', apiKeyCreatedByUser: false, @@ -189,6 +196,7 @@ const mockCreatePointInTimeFinderAsInternalUser = ( describe('BackfillClient', () => { let backfillClient: BackfillClient; + let isSystemAction: jest.Mock; beforeAll(() => { jest.useFakeTimers().setSystemTime(new Date('2024-01-30T00:00:00.000Z')); @@ -196,6 +204,9 @@ describe('BackfillClient', () => { beforeEach(() => { jest.resetAllMocks(); + isSystemAction = jest.fn().mockReturnValue(false); + actionsClient.isSystemAction.mockImplementation(isSystemAction); + ruleTypeRegistry.get.mockReturnValue(mockRuleType); backfillClient = new BackfillClient({ logger, @@ -271,6 +282,7 @@ describe('BackfillClient', () => { unsecuredSavedObjectsClient.bulkCreate.mockResolvedValueOnce(bulkCreateResult); const result = await backfillClient.bulkQueue({ + actionsClient, auditLogger, params: mockData, rules: mockRules, @@ -332,11 +344,1163 @@ describe('BackfillClient', () => { ]); expect(result).toEqual( bulkCreateResult.saved_objects.map((so, index) => - transformAdHocRunToBackfillResult(so, bulkCreateParams?.[index]) + transformAdHocRunToBackfillResult({ + adHocRunSO: so, + isSystemAction, + originalSO: bulkCreateParams?.[index], + }) + ) + ); + }); + + test('should successfully schedule backfill for rule with actions when runActions=true', async () => { + actionsClient.getBulk.mockResolvedValue([ + { + id: '987', + actionTypeId: 'test', + config: { + from: 'me@me.com', + hasAuth: false, + host: 'hello', + port: 22, + secure: null, + service: null, + }, + isMissingSecrets: false, + name: 'email connector', + isPreconfigured: false, + isSystemAction: false, + isDeprecated: false, + }, + ]); + const mockData = [ + getMockData(), + getMockData({ ruleId: '2', end: '2023-11-17T08:00:00.000Z' }), + ]; + const rule1 = getMockRule({ + actions: [ + { + group: 'default', + id: '987', + actionTypeId: 'test', + params: {}, + uuid: '123abc', + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + }, + { + group: 'default', + id: '987', + actionTypeId: 'test', + params: {}, + uuid: 'xyz987', + frequency: { notifyWhen: 'onActiveAlert', summary: true, throttle: null }, + }, + ], + }); + const rule2 = getMockRule({ + id: '2', + actions: [ + { + group: 'default', + id: '987', + actionTypeId: 'test', + params: {}, + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + }, + ], + }); + const mockRules = [rule1, rule2]; + ruleTypeRegistry.get.mockReturnValue({ ...mockRuleType, ruleTaskTimeout: '1d' }); + + const mockAttributes1 = getMockAdHocRunAttributes({ + overwrites: { + start: '2023-11-16T08:00:00.000Z', + end: '2023-11-16T20:00:00.000Z', + schedule: [ + { + runAt: '2023-11-16T20:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + ], + }, + actions: [], + }); + const mockAttributes2 = getMockAdHocRunAttributes({ + overwrites: { + start: '2023-11-16T08:00:00.000Z', + end: '2023-11-17T08:00:00.000Z', + schedule: [ + { + runAt: '2023-11-16T20:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + { + runAt: '2023-11-17T08:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + ], + }, + }); + const bulkCreateResult = { + saved_objects: [ + getBulkCreateParam('abc', '1', mockAttributes1), + getBulkCreateParam('def', '2', mockAttributes2), + ], + }; + + unsecuredSavedObjectsClient.bulkCreate.mockResolvedValueOnce(bulkCreateResult); + + const result = await backfillClient.bulkQueue({ + actionsClient, + auditLogger, + params: mockData, + rules: mockRules, + ruleTypeRegistry, + spaceId: 'default', + unsecuredSavedObjectsClient, + }); + + const bulkCreateParams = [ + { + type: AD_HOC_RUN_SAVED_OBJECT_TYPE, + attributes: { + ...mockAttributes1, + rule: { + ...mockAttributes1.rule, + actions: [ + { + actionRef: 'action_0', + group: 'default', + actionTypeId: 'test', + params: {}, + uuid: '123abc', + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + } as RawRuleAction, + { + actionRef: 'action_1', + group: 'default', + actionTypeId: 'test', + params: {}, + uuid: 'xyz987', + frequency: { notifyWhen: 'onActiveAlert', summary: true, throttle: null }, + } as RawRuleAction, + ], + }, + }, + references: [ + { id: rule1.id, name: 'rule', type: RULE_SAVED_OBJECT_TYPE }, + { id: '987', name: 'action_0', type: 'action' }, + { id: '987', name: 'action_1', type: 'action' }, + ], + }, + { + type: AD_HOC_RUN_SAVED_OBJECT_TYPE, + attributes: { + ...mockAttributes2, + rule: { + ...mockAttributes1.rule, + actions: [ + { + actionRef: 'action_0', + group: 'default', + actionTypeId: 'test', + params: {}, + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + } as RawRuleAction, + ], + }, + }, + references: [ + { id: rule2.id, name: 'rule', type: RULE_SAVED_OBJECT_TYPE }, + { id: '987', name: 'action_0', type: 'action' }, + ], + }, + ]; + + expect(unsecuredSavedObjectsClient.bulkCreate).toHaveBeenCalledWith(bulkCreateParams); + expect(auditLogger.log).toHaveBeenCalledTimes(2); + expect(auditLogger.log).toHaveBeenNthCalledWith(1, { + event: { + action: 'ad_hoc_run_create', + category: ['database'], + outcome: 'success', + type: ['creation'], + }, + kibana: { saved_object: { id: 'abc', type: 'ad_hoc_run_params' } }, + message: 'User has created ad hoc run for ad_hoc_run_params [id=abc]', + }); + expect(auditLogger.log).toHaveBeenNthCalledWith(2, { + event: { + action: 'ad_hoc_run_create', + category: ['database'], + outcome: 'success', + type: ['creation'], + }, + kibana: { saved_object: { id: 'def', type: 'ad_hoc_run_params' } }, + message: 'User has created ad hoc run for ad_hoc_run_params [id=def]', + }); + expect(taskManagerStart.bulkSchedule).toHaveBeenCalledWith([ + { + id: 'abc', + taskType: 'ad_hoc_run-backfill', + state: {}, + timeoutOverride: '1d', + params: { adHocRunParamsId: 'abc', spaceId: 'default' }, + }, + { + id: 'def', + taskType: 'ad_hoc_run-backfill', + state: {}, + timeoutOverride: '1d', + params: { adHocRunParamsId: 'def', spaceId: 'default' }, + }, + ]); + expect(result).toEqual( + bulkCreateResult.saved_objects.map((so, index) => + transformAdHocRunToBackfillResult({ + adHocRunSO: so, + isSystemAction, + originalSO: bulkCreateParams?.[index], + }) ) ); }); + test('should successfully schedule backfill for rule with rule-level notifyWhen field', async () => { + actionsClient.getBulk.mockResolvedValue([ + { + id: '987', + actionTypeId: 'test', + config: { + from: 'me@me.com', + hasAuth: false, + host: 'hello', + port: 22, + secure: null, + service: null, + }, + isMissingSecrets: false, + name: 'email connector', + isPreconfigured: false, + isSystemAction: false, + isDeprecated: false, + }, + ]); + const mockData = [ + getMockData(), + getMockData({ ruleId: '2', end: '2023-11-17T08:00:00.000Z' }), + ]; + const rule1 = getMockRule({ + notifyWhen: 'onActiveAlert', + actions: [ + { + group: 'default', + id: '987', + actionTypeId: 'test', + params: {}, + uuid: '123abc', + }, + { + group: 'default', + id: '987', + actionTypeId: 'test', + params: {}, + uuid: 'xyz987', + }, + ], + }); + const rule2 = getMockRule({ + id: '2', + notifyWhen: 'onActiveAlert', + actions: [ + { + group: 'default', + id: '987', + actionTypeId: 'test', + params: {}, + }, + ], + }); + const mockRules = [rule1, rule2]; + ruleTypeRegistry.get.mockReturnValue({ ...mockRuleType, ruleTaskTimeout: '1d' }); + + const mockAttributes1 = getMockAdHocRunAttributes({ + overwrites: { + start: '2023-11-16T08:00:00.000Z', + end: '2023-11-16T20:00:00.000Z', + schedule: [ + { + runAt: '2023-11-16T20:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + ], + }, + actions: [], + }); + const mockAttributes2 = getMockAdHocRunAttributes({ + overwrites: { + start: '2023-11-16T08:00:00.000Z', + end: '2023-11-17T08:00:00.000Z', + schedule: [ + { + runAt: '2023-11-16T20:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + { + runAt: '2023-11-17T08:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + ], + }, + }); + const bulkCreateResult = { + saved_objects: [ + getBulkCreateParam('abc', '1', mockAttributes1), + getBulkCreateParam('def', '2', mockAttributes2), + ], + }; + + unsecuredSavedObjectsClient.bulkCreate.mockResolvedValueOnce(bulkCreateResult); + + const result = await backfillClient.bulkQueue({ + actionsClient, + auditLogger, + params: mockData, + rules: mockRules, + ruleTypeRegistry, + spaceId: 'default', + unsecuredSavedObjectsClient, + }); + + const bulkCreateParams = [ + { + type: AD_HOC_RUN_SAVED_OBJECT_TYPE, + attributes: { + ...mockAttributes1, + rule: { + ...mockAttributes1.rule, + actions: [ + { + actionRef: 'action_0', + group: 'default', + actionTypeId: 'test', + params: {}, + uuid: '123abc', + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + } as RawRuleAction, + { + actionRef: 'action_1', + group: 'default', + actionTypeId: 'test', + params: {}, + uuid: 'xyz987', + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + } as RawRuleAction, + ], + }, + }, + references: [ + { id: rule1.id, name: 'rule', type: RULE_SAVED_OBJECT_TYPE }, + { id: '987', name: 'action_0', type: 'action' }, + { id: '987', name: 'action_1', type: 'action' }, + ], + }, + { + type: AD_HOC_RUN_SAVED_OBJECT_TYPE, + attributes: { + ...mockAttributes2, + rule: { + ...mockAttributes1.rule, + actions: [ + { + actionRef: 'action_0', + group: 'default', + actionTypeId: 'test', + params: {}, + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + } as RawRuleAction, + ], + }, + }, + references: [ + { id: rule2.id, name: 'rule', type: RULE_SAVED_OBJECT_TYPE }, + { id: '987', name: 'action_0', type: 'action' }, + ], + }, + ]; + + expect(unsecuredSavedObjectsClient.bulkCreate).toHaveBeenCalledWith(bulkCreateParams); + expect(auditLogger.log).toHaveBeenCalledTimes(2); + expect(auditLogger.log).toHaveBeenNthCalledWith(1, { + event: { + action: 'ad_hoc_run_create', + category: ['database'], + outcome: 'success', + type: ['creation'], + }, + kibana: { saved_object: { id: 'abc', type: 'ad_hoc_run_params' } }, + message: 'User has created ad hoc run for ad_hoc_run_params [id=abc]', + }); + expect(auditLogger.log).toHaveBeenNthCalledWith(2, { + event: { + action: 'ad_hoc_run_create', + category: ['database'], + outcome: 'success', + type: ['creation'], + }, + kibana: { saved_object: { id: 'def', type: 'ad_hoc_run_params' } }, + message: 'User has created ad hoc run for ad_hoc_run_params [id=def]', + }); + expect(taskManagerStart.bulkSchedule).toHaveBeenCalledWith([ + { + id: 'abc', + taskType: 'ad_hoc_run-backfill', + state: {}, + timeoutOverride: '1d', + params: { adHocRunParamsId: 'abc', spaceId: 'default' }, + }, + { + id: 'def', + taskType: 'ad_hoc_run-backfill', + state: {}, + timeoutOverride: '1d', + params: { adHocRunParamsId: 'def', spaceId: 'default' }, + }, + ]); + expect(result).toEqual( + bulkCreateResult.saved_objects.map((so, index) => + transformAdHocRunToBackfillResult({ + adHocRunSO: so, + isSystemAction, + originalSO: bulkCreateParams?.[index], + }) + ) + ); + }); + + test('should ignore actions for rule with actions when runActions=false', async () => { + const mockData = [ + getMockData({ runActions: false }), + getMockData({ ruleId: '2', end: '2023-11-17T08:00:00.000Z', runActions: false }), + ]; + const rule1 = getMockRule({ + actions: [ + { + group: 'default', + id: '987', + actionTypeId: 'test', + params: {}, + uuid: '123abc', + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + }, + { + group: 'default', + id: '987', + actionTypeId: 'test', + params: {}, + uuid: 'xyz987', + frequency: { notifyWhen: 'onActiveAlert', summary: true, throttle: null }, + }, + ], + }); + const rule2 = getMockRule({ + id: '2', + actions: [ + { + group: 'default', + id: '987', + actionTypeId: 'test', + params: {}, + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + }, + ], + }); + const mockRules = [rule1, rule2]; + ruleTypeRegistry.get.mockReturnValue({ ...mockRuleType, ruleTaskTimeout: '1d' }); + + const mockAttributes1 = getMockAdHocRunAttributes({ + overwrites: { + start: '2023-11-16T08:00:00.000Z', + end: '2023-11-16T20:00:00.000Z', + schedule: [ + { + runAt: '2023-11-16T20:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + ], + }, + actions: [], + }); + const mockAttributes2 = getMockAdHocRunAttributes({ + overwrites: { + start: '2023-11-16T08:00:00.000Z', + end: '2023-11-17T08:00:00.000Z', + schedule: [ + { + runAt: '2023-11-16T20:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + { + runAt: '2023-11-17T08:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + ], + }, + }); + const bulkCreateResult = { + saved_objects: [ + getBulkCreateParam('abc', '1', mockAttributes1), + getBulkCreateParam('def', '2', mockAttributes2), + ], + }; + + unsecuredSavedObjectsClient.bulkCreate.mockResolvedValueOnce(bulkCreateResult); + + const result = await backfillClient.bulkQueue({ + actionsClient, + auditLogger, + params: mockData, + rules: mockRules, + ruleTypeRegistry, + spaceId: 'default', + unsecuredSavedObjectsClient, + }); + + const bulkCreateParams = [ + { + type: AD_HOC_RUN_SAVED_OBJECT_TYPE, + attributes: mockAttributes1, + references: [{ id: rule1.id, name: 'rule', type: RULE_SAVED_OBJECT_TYPE }], + }, + { + type: AD_HOC_RUN_SAVED_OBJECT_TYPE, + attributes: mockAttributes2, + references: [{ id: rule2.id, name: 'rule', type: RULE_SAVED_OBJECT_TYPE }], + }, + ]; + + expect(unsecuredSavedObjectsClient.bulkCreate).toHaveBeenCalledWith(bulkCreateParams); + expect(auditLogger.log).toHaveBeenCalledTimes(2); + expect(auditLogger.log).toHaveBeenNthCalledWith(1, { + event: { + action: 'ad_hoc_run_create', + category: ['database'], + outcome: 'success', + type: ['creation'], + }, + kibana: { saved_object: { id: 'abc', type: 'ad_hoc_run_params' } }, + message: 'User has created ad hoc run for ad_hoc_run_params [id=abc]', + }); + expect(auditLogger.log).toHaveBeenNthCalledWith(2, { + event: { + action: 'ad_hoc_run_create', + category: ['database'], + outcome: 'success', + type: ['creation'], + }, + kibana: { saved_object: { id: 'def', type: 'ad_hoc_run_params' } }, + message: 'User has created ad hoc run for ad_hoc_run_params [id=def]', + }); + expect(taskManagerStart.bulkSchedule).toHaveBeenCalledWith([ + { + id: 'abc', + taskType: 'ad_hoc_run-backfill', + state: {}, + timeoutOverride: '1d', + params: { adHocRunParamsId: 'abc', spaceId: 'default' }, + }, + { + id: 'def', + taskType: 'ad_hoc_run-backfill', + state: {}, + timeoutOverride: '1d', + params: { adHocRunParamsId: 'def', spaceId: 'default' }, + }, + ]); + expect(result).toEqual( + bulkCreateResult.saved_objects.map((so, index) => + transformAdHocRunToBackfillResult({ + adHocRunSO: so, + isSystemAction, + originalSO: bulkCreateParams?.[index], + }) + ) + ); + }); + + test('should successfully schedule backfill for rule with system actions when runActions=true', async () => { + actionsClient.isSystemAction.mockReturnValueOnce(false); + actionsClient.isSystemAction.mockReturnValueOnce(true); + actionsClient.getBulk.mockResolvedValue([ + { + id: '987', + actionTypeId: 'test', + config: { + from: 'me@me.com', + hasAuth: false, + host: 'hello', + port: 22, + secure: null, + service: null, + }, + isMissingSecrets: false, + name: 'email connector', + isPreconfigured: false, + isSystemAction: false, + isDeprecated: false, + }, + { + id: 'system_456', + actionTypeId: 'test.system', + name: 'System action: .cases', + config: {}, + isDeprecated: false, + isMissingSecrets: false, + isPreconfigured: false, + isSystemAction: true, + }, + ]); + const mockData = [getMockData()]; + const rule = getMockRule({ + actions: [ + { + group: 'default', + id: '987', + actionTypeId: 'test', + params: {}, + uuid: '123abc', + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + }, + ], + systemActions: [ + { + id: 'system_456', + actionTypeId: 'test.system', + params: {}, + uuid: 'aaaaaa', + }, + ], + }); + const mockRules = [rule]; + ruleTypeRegistry.get.mockReturnValue({ ...mockRuleType, ruleTaskTimeout: '1d' }); + + const mockAttributes = getMockAdHocRunAttributes({ + overwrites: { + start: '2023-11-16T08:00:00.000Z', + end: '2023-11-16T20:00:00.000Z', + schedule: [ + { + runAt: '2023-11-16T20:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + ], + }, + actions: [], + }); + + const bulkCreateResult = { + saved_objects: [getBulkCreateParam('abc', '1', mockAttributes)], + }; + + unsecuredSavedObjectsClient.bulkCreate.mockResolvedValueOnce(bulkCreateResult); + + const result = await backfillClient.bulkQueue({ + actionsClient, + auditLogger, + params: mockData, + rules: mockRules, + ruleTypeRegistry, + spaceId: 'default', + unsecuredSavedObjectsClient, + }); + + const bulkCreateParams = [ + { + type: AD_HOC_RUN_SAVED_OBJECT_TYPE, + attributes: { + ...mockAttributes, + rule: { + ...mockAttributes.rule, + actions: [ + { + actionRef: 'action_0', + group: 'default', + actionTypeId: 'test', + params: {}, + uuid: '123abc', + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + } as RawRuleAction, + { + actionRef: 'system_action:system_456', + actionTypeId: 'test.system', + params: {}, + uuid: 'aaaaaa', + } as RawRuleAction, + ], + }, + }, + references: [ + { id: rule.id, name: 'rule', type: RULE_SAVED_OBJECT_TYPE }, + { id: '987', name: 'action_0', type: 'action' }, + ], + }, + ]; + + expect(unsecuredSavedObjectsClient.bulkCreate).toHaveBeenCalledWith(bulkCreateParams); + expect(auditLogger.log).toHaveBeenCalledTimes(1); + expect(auditLogger.log).toHaveBeenNthCalledWith(1, { + event: { + action: 'ad_hoc_run_create', + category: ['database'], + outcome: 'success', + type: ['creation'], + }, + kibana: { saved_object: { id: 'abc', type: 'ad_hoc_run_params' } }, + message: 'User has created ad hoc run for ad_hoc_run_params [id=abc]', + }); + expect(taskManagerStart.bulkSchedule).toHaveBeenCalledWith([ + { + id: 'abc', + taskType: 'ad_hoc_run-backfill', + state: {}, + timeoutOverride: '1d', + params: { adHocRunParamsId: 'abc', spaceId: 'default' }, + }, + ]); + expect(result).toEqual( + bulkCreateResult.saved_objects.map((so, index) => + transformAdHocRunToBackfillResult({ + adHocRunSO: so, + isSystemAction, + originalSO: bulkCreateParams?.[index], + }) + ) + ); + }); + + test('should schedule backfill for rule with unsupported actions and return warning', async () => { + actionsClient.getBulk.mockResolvedValue([ + { + id: '987', + actionTypeId: 'test', + config: { + from: 'me@me.com', + hasAuth: false, + host: 'hello', + port: 22, + secure: null, + service: null, + }, + isMissingSecrets: false, + name: 'email connector', + isPreconfigured: false, + isSystemAction: false, + isDeprecated: false, + }, + ]); + const mockData = [ + getMockData(), + getMockData({ ruleId: '2', end: '2023-11-17T08:00:00.000Z' }), + ]; + const rule1 = getMockRule({ + actions: [ + { + group: 'default', + id: '987', + actionTypeId: 'test', + params: {}, + uuid: '123abc', + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + }, + { + group: 'default', + id: '987', + actionTypeId: 'test', + params: {}, + uuid: 'xyz987', + frequency: { notifyWhen: 'onThrottleInterval', summary: true, throttle: '1h' }, + }, + ], + }); + const rule2 = getMockRule({ + id: '2', + actions: [ + { + group: 'default', + id: '987', + actionTypeId: 'test', + params: {}, + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + }, + ], + }); + const mockRules = [rule1, rule2]; + ruleTypeRegistry.get.mockReturnValue({ ...mockRuleType, ruleTaskTimeout: '1d' }); + + const mockAttributes1 = getMockAdHocRunAttributes({ + overwrites: { + start: '2023-11-16T08:00:00.000Z', + end: '2023-11-16T20:00:00.000Z', + schedule: [ + { + runAt: '2023-11-16T20:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + ], + }, + actions: [], + }); + const mockAttributes2 = getMockAdHocRunAttributes({ + overwrites: { + start: '2023-11-16T08:00:00.000Z', + end: '2023-11-17T08:00:00.000Z', + schedule: [ + { + runAt: '2023-11-16T20:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + { + runAt: '2023-11-17T08:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + ], + }, + }); + const bulkCreateResult = { + saved_objects: [ + getBulkCreateParam('abc', '1', mockAttributes1), + getBulkCreateParam('def', '2', mockAttributes2), + ], + }; + + unsecuredSavedObjectsClient.bulkCreate.mockResolvedValueOnce(bulkCreateResult); + + const result = await backfillClient.bulkQueue({ + actionsClient, + auditLogger, + params: mockData, + rules: mockRules, + ruleTypeRegistry, + spaceId: 'default', + unsecuredSavedObjectsClient, + }); + + const bulkCreateParams = [ + { + type: AD_HOC_RUN_SAVED_OBJECT_TYPE, + attributes: { + ...mockAttributes1, + rule: { + ...mockAttributes1.rule, + actions: [ + { + actionRef: 'action_0', + group: 'default', + actionTypeId: 'test', + params: {}, + uuid: '123abc', + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + } as RawRuleAction, + ], + }, + }, + references: [ + { id: rule1.id, name: 'rule', type: RULE_SAVED_OBJECT_TYPE }, + { id: '987', name: 'action_0', type: 'action' }, + ], + }, + { + type: AD_HOC_RUN_SAVED_OBJECT_TYPE, + attributes: { + ...mockAttributes2, + rule: { + ...mockAttributes1.rule, + actions: [ + { + actionRef: 'action_0', + group: 'default', + actionTypeId: 'test', + params: {}, + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + } as RawRuleAction, + ], + }, + }, + references: [ + { id: rule2.id, name: 'rule', type: RULE_SAVED_OBJECT_TYPE }, + { id: '987', name: 'action_0', type: 'action' }, + ], + }, + ]; + + expect(unsecuredSavedObjectsClient.bulkCreate).toHaveBeenCalledWith(bulkCreateParams); + expect(auditLogger.log).toHaveBeenCalledTimes(2); + expect(auditLogger.log).toHaveBeenNthCalledWith(1, { + event: { + action: 'ad_hoc_run_create', + category: ['database'], + outcome: 'success', + type: ['creation'], + }, + kibana: { saved_object: { id: 'abc', type: 'ad_hoc_run_params' } }, + message: 'User has created ad hoc run for ad_hoc_run_params [id=abc]', + }); + expect(auditLogger.log).toHaveBeenNthCalledWith(2, { + event: { + action: 'ad_hoc_run_create', + category: ['database'], + outcome: 'success', + type: ['creation'], + }, + kibana: { saved_object: { id: 'def', type: 'ad_hoc_run_params' } }, + message: 'User has created ad hoc run for ad_hoc_run_params [id=def]', + }); + expect(taskManagerStart.bulkSchedule).toHaveBeenCalledWith([ + { + id: 'abc', + taskType: 'ad_hoc_run-backfill', + state: {}, + timeoutOverride: '1d', + params: { adHocRunParamsId: 'abc', spaceId: 'default' }, + }, + { + id: 'def', + taskType: 'ad_hoc_run-backfill', + state: {}, + timeoutOverride: '1d', + params: { adHocRunParamsId: 'def', spaceId: 'default' }, + }, + ]); + expect(result).toEqual([ + { + ...transformAdHocRunToBackfillResult({ + adHocRunSO: bulkCreateResult.saved_objects[0], + isSystemAction, + originalSO: bulkCreateParams?.[0], + }), + warnings: [ + 'Rule has actions that are not supported for backfill. Those actions will be skipped.', + ], + }, + transformAdHocRunToBackfillResult({ + adHocRunSO: bulkCreateResult.saved_objects[1], + isSystemAction, + originalSO: bulkCreateParams?.[1], + }), + ]); + }); + + test('should schedule backfill for rule with unsupported rule-level notifyWhen field and return warning', async () => { + actionsClient.getBulk.mockResolvedValue([ + { + id: '987', + actionTypeId: 'test', + config: { + from: 'me@me.com', + hasAuth: false, + host: 'hello', + port: 22, + secure: null, + service: null, + }, + isMissingSecrets: false, + name: 'email connector', + isPreconfigured: false, + isSystemAction: false, + isDeprecated: false, + }, + ]); + const mockData = [ + getMockData(), + getMockData({ ruleId: '2', end: '2023-11-17T08:00:00.000Z' }), + ]; + const rule1 = getMockRule({ + notifyWhen: 'onThrottleInterval', + throttle: '12h', + actions: [ + { + group: 'default', + id: '987', + actionTypeId: 'test', + params: {}, + uuid: '123abc', + }, + { + group: 'default', + id: '987', + actionTypeId: 'test', + params: {}, + uuid: 'xyz987', + }, + ], + }); + const rule2 = getMockRule({ + id: '2', + notifyWhen: 'onThrottleInterval', + throttle: '12h', + actions: [ + { + group: 'default', + id: '987', + actionTypeId: 'test', + params: {}, + }, + ], + }); + const mockRules = [rule1, rule2]; + ruleTypeRegistry.get.mockReturnValue({ ...mockRuleType, ruleTaskTimeout: '1d' }); + + const mockAttributes1 = getMockAdHocRunAttributes({ + overwrites: { + start: '2023-11-16T08:00:00.000Z', + end: '2023-11-16T20:00:00.000Z', + schedule: [ + { + runAt: '2023-11-16T20:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + ], + }, + actions: [], + }); + const mockAttributes2 = getMockAdHocRunAttributes({ + overwrites: { + start: '2023-11-16T08:00:00.000Z', + end: '2023-11-17T08:00:00.000Z', + schedule: [ + { + runAt: '2023-11-16T20:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + { + runAt: '2023-11-17T08:00:00.000Z', + interval: '12h', + status: adHocRunStatus.PENDING, + }, + ], + }, + }); + const bulkCreateResult = { + saved_objects: [ + getBulkCreateParam('abc', '1', mockAttributes1), + getBulkCreateParam('def', '2', mockAttributes2), + ], + }; + + unsecuredSavedObjectsClient.bulkCreate.mockResolvedValueOnce(bulkCreateResult); + + const result = await backfillClient.bulkQueue({ + actionsClient, + auditLogger, + params: mockData, + rules: mockRules, + ruleTypeRegistry, + spaceId: 'default', + unsecuredSavedObjectsClient, + }); + + const bulkCreateParams = [ + { + type: AD_HOC_RUN_SAVED_OBJECT_TYPE, + attributes: { + ...mockAttributes1, + rule: { + ...mockAttributes1.rule, + actions: [], + }, + }, + references: [{ id: rule1.id, name: 'rule', type: RULE_SAVED_OBJECT_TYPE }], + }, + { + type: AD_HOC_RUN_SAVED_OBJECT_TYPE, + attributes: { + ...mockAttributes2, + rule: { + ...mockAttributes1.rule, + actions: [], + }, + }, + references: [{ id: rule2.id, name: 'rule', type: RULE_SAVED_OBJECT_TYPE }], + }, + ]; + + expect(unsecuredSavedObjectsClient.bulkCreate).toHaveBeenCalledWith(bulkCreateParams); + expect(auditLogger.log).toHaveBeenCalledTimes(2); + expect(auditLogger.log).toHaveBeenNthCalledWith(1, { + event: { + action: 'ad_hoc_run_create', + category: ['database'], + outcome: 'success', + type: ['creation'], + }, + kibana: { saved_object: { id: 'abc', type: 'ad_hoc_run_params' } }, + message: 'User has created ad hoc run for ad_hoc_run_params [id=abc]', + }); + expect(auditLogger.log).toHaveBeenNthCalledWith(2, { + event: { + action: 'ad_hoc_run_create', + category: ['database'], + outcome: 'success', + type: ['creation'], + }, + kibana: { saved_object: { id: 'def', type: 'ad_hoc_run_params' } }, + message: 'User has created ad hoc run for ad_hoc_run_params [id=def]', + }); + expect(taskManagerStart.bulkSchedule).toHaveBeenCalledWith([ + { + id: 'abc', + taskType: 'ad_hoc_run-backfill', + state: {}, + timeoutOverride: '1d', + params: { adHocRunParamsId: 'abc', spaceId: 'default' }, + }, + { + id: 'def', + taskType: 'ad_hoc_run-backfill', + state: {}, + timeoutOverride: '1d', + params: { adHocRunParamsId: 'def', spaceId: 'default' }, + }, + ]); + expect(result).toEqual([ + { + ...transformAdHocRunToBackfillResult({ + adHocRunSO: bulkCreateResult.saved_objects[0], + isSystemAction, + originalSO: bulkCreateParams?.[0], + }), + warnings: [ + 'Rule has actions that are not supported for backfill. Those actions will be skipped.', + ], + }, + { + ...transformAdHocRunToBackfillResult({ + adHocRunSO: bulkCreateResult.saved_objects[1], + isSystemAction, + originalSO: bulkCreateParams?.[1], + }), + warnings: [ + 'Rule has actions that are not supported for backfill. Those actions will be skipped.', + ], + }, + ]); + }); + test('should successfully create multiple backfill saved objects for a single rule', async () => { const mockData = [getMockData(), getMockData({ end: '2023-11-17T08:00:00.000Z' })]; const rule1 = getMockRule(); @@ -383,6 +1547,7 @@ describe('BackfillClient', () => { unsecuredSavedObjectsClient.bulkCreate.mockResolvedValueOnce(bulkCreateResult); const result = await backfillClient.bulkQueue({ + actionsClient, auditLogger, params: mockData, rules: mockRules, @@ -442,7 +1607,11 @@ describe('BackfillClient', () => { ]); expect(result).toEqual( bulkCreateResult.saved_objects.map((so, index) => - transformAdHocRunToBackfillResult(so, bulkCreateParams?.[index]) + transformAdHocRunToBackfillResult({ + adHocRunSO: so, + isSystemAction, + originalSO: bulkCreateParams?.[index], + }) ) ); }); @@ -476,6 +1645,7 @@ describe('BackfillClient', () => { unsecuredSavedObjectsClient.bulkCreate.mockResolvedValueOnce(bulkCreateResult); const result = await backfillClient.bulkQueue({ + actionsClient, auditLogger, params: mockData, rules: mockRules, @@ -504,7 +1674,7 @@ describe('BackfillClient', () => { message: 'User has created ad hoc run for ad_hoc_run_params [id=abc]', }); expect(logger.warn).toHaveBeenCalledWith( - `No rule found for ruleId 2 - not scheduling backfill for {\"ruleId\":\"2\",\"start\":\"2023-11-16T08:00:00.000Z\",\"end\":\"2023-11-17T08:00:00.000Z\"}` + `Error for ruleId 2 - not scheduling backfill for {\"ruleId\":\"2\",\"start\":\"2023-11-16T08:00:00.000Z\",\"runActions\":true,\"end\":\"2023-11-17T08:00:00.000Z\"}` ); expect(taskManagerStart.bulkSchedule).toHaveBeenCalledWith([ { @@ -516,7 +1686,11 @@ describe('BackfillClient', () => { ]); expect(result).toEqual([ ...bulkCreateResult.saved_objects.map((so, index) => - transformAdHocRunToBackfillResult(so, bulkCreateParams?.[0]) + transformAdHocRunToBackfillResult({ + adHocRunSO: so, + isSystemAction, + originalSO: bulkCreateParams?.[index], + }) ), { error: { @@ -591,6 +1765,7 @@ describe('BackfillClient', () => { bulkCreateResult as SavedObjectsBulkResponse ); const result = await backfillClient.bulkQueue({ + actionsClient, auditLogger, params: mockData, rules: mockRules, @@ -739,6 +1914,7 @@ describe('BackfillClient', () => { ]; const result = await backfillClient.bulkQueue({ + actionsClient, auditLogger, params: mockData, rules: [], @@ -842,6 +2018,7 @@ describe('BackfillClient', () => { bulkCreateResult as SavedObjectsBulkResponse ); const result = await backfillClient.bulkQueue({ + actionsClient, params: mockData, rules: mockRules, ruleTypeRegistry, diff --git a/x-pack/platform/plugins/shared/alerting/server/backfill_client/backfill_client.ts b/x-pack/platform/plugins/shared/alerting/server/backfill_client/backfill_client.ts index 48b5e49c428c0..bb4b130e29b31 100644 --- a/x-pack/platform/plugins/shared/alerting/server/backfill_client/backfill_client.ts +++ b/x-pack/platform/plugins/shared/alerting/server/backfill_client/backfill_client.ts @@ -23,9 +23,9 @@ import { TaskPriority, } from '@kbn/task-manager-plugin/server'; import { isNumber } from 'lodash'; +import { ActionsClient } from '@kbn/actions-plugin/server'; import { ScheduleBackfillError, - ScheduleBackfillParam, ScheduleBackfillParams, ScheduleBackfillResult, ScheduleBackfillResults, @@ -42,6 +42,8 @@ import { AD_HOC_RUN_SAVED_OBJECT_TYPE, RULE_SAVED_OBJECT_TYPE } from '../saved_o import { TaskRunnerFactory } from '../task_runner'; import { RuleTypeRegistry } from '../types'; import { createBackfillError } from './lib'; +import { denormalizeActions } from '../rules_client/lib/denormalize_actions'; +import { DenormalizedAction, NormalizedAlertActionWithGeneratedValues } from '../rules_client'; export const BACKFILL_TASK_TYPE = 'ad_hoc_run-backfill'; @@ -53,6 +55,7 @@ interface ConstructorOpts { } interface BulkQueueOpts { + actionsClient: ActionsClient; auditLogger?: AuditLogger; params: ScheduleBackfillParams; rules: RuleDomain[]; @@ -86,6 +89,7 @@ export class BackfillClient { } public async bulkQueue({ + actionsClient, auditLogger, params, rules, @@ -117,10 +121,16 @@ export class BackfillClient { */ const soToCreateIndexOrErrorMap: Map = new Map(); + const rulesWithUnsupportedActions = new Set(); - params.forEach((param: ScheduleBackfillParam, ndx: number) => { + for (let ndx = 0; ndx < params.length; ndx++) { + const param = params[ndx]; // For this schedule request, look up the rule or return error - const { rule, error } = getRuleOrError(param.ruleId, rules, ruleTypeRegistry); + const { rule, error } = getRuleOrError({ + ruleId: param.ruleId, + rules, + ruleTypeRegistry, + }); if (rule) { // keep track of index of this request in the adHocSOsToCreate array soToCreateIndexOrErrorMap.set(ndx, adHocSOsToCreate.length); @@ -129,22 +139,31 @@ export class BackfillClient { name: `rule`, type: RULE_SAVED_OBJECT_TYPE, }; + + const { actions, hasUnsupportedActions, references } = await extractRuleActions({ + actionsClient, + rule, + runActions: param.runActions, + }); + + if (hasUnsupportedActions) { + rulesWithUnsupportedActions.add(ndx); + } + adHocSOsToCreate.push({ type: AD_HOC_RUN_SAVED_OBJECT_TYPE, - attributes: transformBackfillParamToAdHocRun(param, rule, spaceId), - references: [reference], + attributes: transformBackfillParamToAdHocRun(param, rule, actions, spaceId), + references: [reference, ...references], }); } else if (error) { // keep track of the error encountered for this request by index so // we can return it in order soToCreateIndexOrErrorMap.set(ndx, error); this.logger.warn( - `No rule found for ruleId ${param.ruleId} - not scheduling backfill for ${JSON.stringify( - param - )}` + `Error for ruleId ${param.ruleId} - not scheduling backfill for ${JSON.stringify(param)}` ); } - }); + } // Every request encountered an error, so short-circuit the logic here if (!adHocSOsToCreate.length) { @@ -175,7 +194,11 @@ export class BackfillClient { }) ); } - return transformAdHocRunToBackfillResult(so, adHocSOsToCreate?.[index]); + return transformAdHocRunToBackfillResult({ + adHocRunSO: so, + isSystemAction: (id: string) => actionsClient.isSystemAction(id), + originalSO: adHocSOsToCreate?.[index], + }); } ); @@ -202,7 +225,16 @@ export class BackfillClient { if (isNumber(indexOrError)) { // This number is the index of the response from the savedObjects bulkCreate function - return transformedResponse[indexOrError]; + const response = transformedResponse[indexOrError]; + if (rulesWithUnsupportedActions.has(indexOrError)) { + return { + ...response, + warnings: [ + `Rule has actions that are not supported for backfill. Those actions will be skipped.`, + ], + }; + } + return response; } else { // Return the error we encountered return indexOrError as ScheduleBackfillError; @@ -301,11 +333,16 @@ export class BackfillClient { } } -function getRuleOrError( - ruleId: string, - rules: RuleDomain[], - ruleTypeRegistry: RuleTypeRegistry -): { rule?: RuleDomain; error?: ScheduleBackfillError } { +interface GetRuleOrErrorOpts { + ruleId: string; + rules: RuleDomain[]; + ruleTypeRegistry: RuleTypeRegistry; +} + +function getRuleOrError({ ruleId, rules, ruleTypeRegistry }: GetRuleOrErrorOpts): { + rule?: RuleDomain; + error?: ScheduleBackfillError; +} { const rule = rules.find((r: RuleDomain) => r.id === ruleId); // if rule not found, return not found error @@ -345,3 +382,55 @@ function getRuleOrError( return { rule }; } + +interface ExtractRuleActions { + actionsClient: ActionsClient; + rule: RuleDomain; + runActions?: boolean; +} + +interface ExtractRuleActionsResult { + actions: DenormalizedAction[]; + hasUnsupportedActions: boolean; + references: SavedObjectReference[]; +} + +async function extractRuleActions({ + actionsClient, + rule, + runActions, +}: ExtractRuleActions): Promise { + // defauts to true if not specified + const shouldRunActions = runActions !== undefined ? runActions : true; + + if (!shouldRunActions) { + return { hasUnsupportedActions: false, actions: [], references: [] }; + } + + const ruleLevelNotifyWhen = rule.notifyWhen; + const normalizedActions = []; + for (const action of rule.actions) { + // if action level frequency is not defined and rule level notifyWhen is, set the action level frequency + if (!action.frequency && ruleLevelNotifyWhen) { + normalizedActions.push({ + ...action, + frequency: { notifyWhen: ruleLevelNotifyWhen, summary: false, throttle: null }, + }); + } else { + normalizedActions.push(action); + } + } + + const hasUnsupportedActions = normalizedActions.some( + (action) => action.frequency?.notifyWhen !== 'onActiveAlert' + ); + + const allActions = [ + ...normalizedActions.filter((action) => action.frequency?.notifyWhen === 'onActiveAlert'), + ...(rule.systemActions ?? []), + ] as NormalizedAlertActionWithGeneratedValues[]; + + const { references, actions } = await denormalizeActions(actionsClient, allActions); + + return { hasUnsupportedActions, actions, references }; +} diff --git a/x-pack/platform/plugins/shared/alerting/server/data/ad_hoc_run/types/ad_hoc_run.ts b/x-pack/platform/plugins/shared/alerting/server/data/ad_hoc_run/types/ad_hoc_run.ts index be03f45749c5d..ca4bbe91cd41f 100644 --- a/x-pack/platform/plugins/shared/alerting/server/data/ad_hoc_run/types/ad_hoc_run.ts +++ b/x-pack/platform/plugins/shared/alerting/server/data/ad_hoc_run/types/ad_hoc_run.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { RawRule } from '../../../types'; import { RuleDomain } from '../../../application/rule/types'; import { AdHocRunStatus } from '../../../../common/constants'; @@ -23,10 +24,11 @@ export interface AdHocRunSchedule extends Record { // the backfill job was scheduled. if there are updates to the rule configuration // after the backfill is scheduled, they will not be reflected during the backfill run. type AdHocRunSORule = Pick< - RuleDomain, + RawRule, | 'name' | 'tags' | 'alertTypeId' + | 'actions' | 'params' | 'apiKeyOwner' | 'apiKeyCreatedByUser' @@ -43,7 +45,7 @@ type AdHocRunSORule = Pick< // This is the rule information after loaded from persistence with the // rule ID injected from the SO references array -type AdHocRunRule = AdHocRunSORule & Pick; +type AdHocRunRule = Omit & Pick; export interface AdHocRunSO extends Record { apiKeyId: string; diff --git a/x-pack/platform/plugins/shared/alerting/server/integration_tests/__snapshots__/alert_as_data_fields.test.ts.snap b/x-pack/platform/plugins/shared/alerting/server/integration_tests/__snapshots__/alert_as_data_fields.test.ts.snap index 0513842a6126b..160d41fa2f677 100644 --- a/x-pack/platform/plugins/shared/alerting/server/integration_tests/__snapshots__/alert_as_data_fields.test.ts.snap +++ b/x-pack/platform/plugins/shared/alerting/server/integration_tests/__snapshots__/alert_as_data_fields.test.ts.snap @@ -1414,6 +1414,21 @@ Object { "required": false, "type": "version", }, + "service.asset.criticality": Object { + "array": false, + "required": false, + "type": "keyword", + }, + "service.risk.calculated_level": Object { + "array": false, + "required": false, + "type": "keyword", + }, + "service.risk.calculated_score_norm": Object { + "array": false, + "required": false, + "type": "float", + }, "signal.ancestors.depth": Object { "path": "kibana.alert.ancestors.depth", "required": false, @@ -2517,6 +2532,21 @@ Object { "required": false, "type": "version", }, + "service.asset.criticality": Object { + "array": false, + "required": false, + "type": "keyword", + }, + "service.risk.calculated_level": Object { + "array": false, + "required": false, + "type": "keyword", + }, + "service.risk.calculated_score_norm": Object { + "array": false, + "required": false, + "type": "float", + }, "signal.ancestors.depth": Object { "path": "kibana.alert.ancestors.depth", "required": false, @@ -3620,6 +3650,21 @@ Object { "required": false, "type": "version", }, + "service.asset.criticality": Object { + "array": false, + "required": false, + "type": "keyword", + }, + "service.risk.calculated_level": Object { + "array": false, + "required": false, + "type": "keyword", + }, + "service.risk.calculated_score_norm": Object { + "array": false, + "required": false, + "type": "float", + }, "signal.ancestors.depth": Object { "path": "kibana.alert.ancestors.depth", "required": false, @@ -4723,6 +4768,21 @@ Object { "required": false, "type": "version", }, + "service.asset.criticality": Object { + "array": false, + "required": false, + "type": "keyword", + }, + "service.risk.calculated_level": Object { + "array": false, + "required": false, + "type": "keyword", + }, + "service.risk.calculated_score_norm": Object { + "array": false, + "required": false, + "type": "float", + }, "signal.ancestors.depth": Object { "path": "kibana.alert.ancestors.depth", "required": false, @@ -5826,6 +5886,21 @@ Object { "required": false, "type": "version", }, + "service.asset.criticality": Object { + "array": false, + "required": false, + "type": "keyword", + }, + "service.risk.calculated_level": Object { + "array": false, + "required": false, + "type": "keyword", + }, + "service.risk.calculated_score_norm": Object { + "array": false, + "required": false, + "type": "float", + }, "signal.ancestors.depth": Object { "path": "kibana.alert.ancestors.depth", "required": false, @@ -6935,6 +7010,21 @@ Object { "required": false, "type": "version", }, + "service.asset.criticality": Object { + "array": false, + "required": false, + "type": "keyword", + }, + "service.risk.calculated_level": Object { + "array": false, + "required": false, + "type": "keyword", + }, + "service.risk.calculated_score_norm": Object { + "array": false, + "required": false, + "type": "float", + }, "signal.ancestors.depth": Object { "path": "kibana.alert.ancestors.depth", "required": false, @@ -8038,6 +8128,21 @@ Object { "required": false, "type": "version", }, + "service.asset.criticality": Object { + "array": false, + "required": false, + "type": "keyword", + }, + "service.risk.calculated_level": Object { + "array": false, + "required": false, + "type": "keyword", + }, + "service.risk.calculated_score_norm": Object { + "array": false, + "required": false, + "type": "float", + }, "signal.ancestors.depth": Object { "path": "kibana.alert.ancestors.depth", "required": false, @@ -9141,6 +9246,21 @@ Object { "required": false, "type": "version", }, + "service.asset.criticality": Object { + "array": false, + "required": false, + "type": "keyword", + }, + "service.risk.calculated_level": Object { + "array": false, + "required": false, + "type": "keyword", + }, + "service.risk.calculated_score_norm": Object { + "array": false, + "required": false, + "type": "float", + }, "signal.ancestors.depth": Object { "path": "kibana.alert.ancestors.depth", "required": false, diff --git a/x-pack/platform/plugins/shared/alerting/server/invalidate_pending_api_keys/task.test.ts b/x-pack/platform/plugins/shared/alerting/server/invalidate_pending_api_keys/task.test.ts index a7177b2489740..3c70c6fd314d4 100644 --- a/x-pack/platform/plugins/shared/alerting/server/invalidate_pending_api_keys/task.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/invalidate_pending_api_keys/task.test.ts @@ -17,6 +17,7 @@ import { invalidateApiKeysAndDeletePendingApiKeySavedObject, runInvalidate, } from './task'; +import { ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE } from '@kbn/actions-plugin/server/constants/saved_objects'; let fakeTimer: sinon.SinonFakeTimers; const encryptedSavedObjectsClient = encryptedSavedObjectsMock.createClient(); @@ -92,17 +93,24 @@ describe('Invalidate API Keys Task', () => { encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce( mockInvalidatePendingApiKeyObject2 ); + // first call to find aggregates any AD_HOC_RUN_SAVED_OBJECT_TYPE SOs by apiKeyId internalSavedObjectsRepository.find.mockResolvedValueOnce({ saved_objects: [], total: 2, page: 1, per_page: 10, aggregations: { - apiKeyId: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [], - }, + apiKeyId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + }); + // second call to find aggregates any ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE SOs by apiKeyId + internalSavedObjectsRepository.find.mockResolvedValueOnce({ + saved_objects: [], + total: 1, + page: 1, + per_page: 10, + aggregations: { + apiKeyId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, }, }); @@ -166,13 +174,114 @@ describe('Invalidate API Keys Task', () => { }); }); - test('should get decrypted api key pending invalidation saved object when some api keys are still in use', async () => { + test('should get decrypted api key pending invalidation saved object when some api keys are still in use by AD_HOC_RUN_SAVED_OBJECT_TYPE', async () => { encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce( mockInvalidatePendingApiKeyObject1 ); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce( mockInvalidatePendingApiKeyObject2 ); + // first call to find aggregates any AD_HOC_RUN_SAVED_OBJECT_TYPE SOs by apiKeyId + internalSavedObjectsRepository.find.mockResolvedValueOnce({ + saved_objects: [], + total: 2, + page: 1, + per_page: 10, + aggregations: { + apiKeyId: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'abcd====!', doc_count: 1 }], + }, + }, + }); + // second call to find aggregates any ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE SOs by apiKeyId + internalSavedObjectsRepository.find.mockResolvedValueOnce({ + saved_objects: [], + total: 1, + page: 1, + per_page: 10, + aggregations: { + apiKeyId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + }); + + const result = await getApiKeyIdsToInvalidate({ + apiKeySOsPendingInvalidation: { + saved_objects: [ + { + id: '1', + type: API_KEY_PENDING_INVALIDATION_TYPE, + score: 0, + attributes: { apiKeyId: 'encryptedencrypted', createdAt: '2024-04-11T17:08:44.035Z' }, + references: [], + }, + { + id: '2', + type: API_KEY_PENDING_INVALIDATION_TYPE, + score: 0, + attributes: { apiKeyId: 'encryptedencrypted', createdAt: '2024-04-11T17:08:44.035Z' }, + references: [], + }, + ], + total: 2, + per_page: 10, + page: 1, + }, + encryptedSavedObjectsClient, + savedObjectsClient: internalSavedObjectsRepository, + }); + + expect(encryptedSavedObjectsClient.getDecryptedAsInternalUser).toHaveBeenCalledTimes(2); + expect(encryptedSavedObjectsClient.getDecryptedAsInternalUser).toHaveBeenNthCalledWith( + 1, + API_KEY_PENDING_INVALIDATION_TYPE, + '1' + ); + expect(encryptedSavedObjectsClient.getDecryptedAsInternalUser).toHaveBeenNthCalledWith( + 2, + API_KEY_PENDING_INVALIDATION_TYPE, + '2' + ); + expect(internalSavedObjectsRepository.find).toHaveBeenCalledWith({ + type: AD_HOC_RUN_SAVED_OBJECT_TYPE, + perPage: 0, + filter: `ad_hoc_run_params.attributes.apiKeyId: "abcd====!" OR ad_hoc_run_params.attributes.apiKeyId: "xyz!==!"`, + namespaces: ['*'], + aggs: { + apiKeyId: { + terms: { + field: `ad_hoc_run_params.attributes.apiKeyId`, + size: 100, + }, + }, + }, + }); + expect(result).toEqual({ + apiKeyIdsToInvalidate: [{ id: '2', apiKeyId: 'xyz!==!' }], + apiKeyIdsToExclude: [{ id: '1', apiKeyId: 'abcd====!' }], + }); + }); + + test('should get decrypted api key pending invalidation saved object when some api keys are still in use by ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE', async () => { + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce( + mockInvalidatePendingApiKeyObject1 + ); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce( + mockInvalidatePendingApiKeyObject2 + ); + // first call to find aggregates any AD_HOC_RUN_SAVED_OBJECT_TYPE SOs by apiKeyId + internalSavedObjectsRepository.find.mockResolvedValueOnce({ + saved_objects: [], + total: 1, + page: 1, + per_page: 10, + aggregations: { + apiKeyId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + }); + + // second call to find aggregates any ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE SOs by apiKeyId internalSavedObjectsRepository.find.mockResolvedValueOnce({ saved_objects: [], total: 2, @@ -299,6 +408,15 @@ describe('Invalidate API Keys Task', () => { per_page: 10, // missing aggregations }); + internalSavedObjectsRepository.find.mockResolvedValueOnce({ + saved_objects: [], + total: 1, + page: 1, + per_page: 10, + aggregations: { + apiKeyId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + }); const result = await getApiKeyIdsToInvalidate({ apiKeySOsPendingInvalidation: { @@ -547,19 +665,28 @@ describe('Invalidate API Keys Task', () => { encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce( mockInvalidatePendingApiKeyObject2 ); + // first call to find aggregates any AD_HOC_RUN_SAVED_OBJECT_TYPE SOs by apiKeyId + internalSavedObjectsRepository.find.mockResolvedValueOnce({ + saved_objects: [], + total: 1, + page: 1, + per_page: 10, + aggregations: { + apiKeyId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + }); + + // second call to find aggregates any ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE SOs by apiKeyId internalSavedObjectsRepository.find.mockResolvedValueOnce({ saved_objects: [], total: 2, page: 1, - per_page: 0, + per_page: 10, aggregations: { - apiKeyId: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [], - }, + apiKeyId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, }, }); + securityMockStart.authc.apiKeys.invalidateAsInternalUser.mockResolvedValue({ invalidated_api_keys: ['1', '2'], previously_invalidated_api_keys: [], @@ -576,7 +703,7 @@ describe('Invalidate API Keys Task', () => { }); expect(result).toEqual(2); - expect(internalSavedObjectsRepository.find).toHaveBeenCalledTimes(2); + expect(internalSavedObjectsRepository.find).toHaveBeenCalledTimes(3); expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(1, { type: API_KEY_PENDING_INVALIDATION_TYPE, filter: `api_key_pending_invalidation.attributes.createdAt <= "1969-12-31T23:00:00.000Z"`, @@ -610,6 +737,20 @@ describe('Invalidate API Keys Task', () => { }, }, }); + expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(3, { + type: ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, + perPage: 0, + filter: `action_task_params.attributes.apiKeyId: "abcd====!" OR action_task_params.attributes.apiKeyId: "xyz!==!"`, + namespaces: ['*'], + aggs: { + apiKeyId: { + terms: { + field: `action_task_params.attributes.apiKeyId`, + size: 100, + }, + }, + }, + }); expect(securityMockStart.authc.apiKeys.invalidateAsInternalUser).toHaveBeenCalledTimes(1); expect(securityMockStart.authc.apiKeys.invalidateAsInternalUser).toHaveBeenCalledWith({ ids: ['abcd====!', 'xyz!==!'], @@ -628,7 +769,7 @@ describe('Invalidate API Keys Task', () => { expect(logger.debug).toHaveBeenCalledWith(`Total invalidated API keys "2"`); }); - test('should succeed when there are API keys to invalidate and API keys to exclude', async () => { + test('should succeed when there are API keys to invalidate and API keys to exclude (AD_HOC_RUN_SAVED_OBJECT_TYPE using apiKeyId)', async () => { internalSavedObjectsRepository.find.mockResolvedValueOnce({ saved_objects: [ { @@ -656,6 +797,8 @@ describe('Invalidate API Keys Task', () => { encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce( mockInvalidatePendingApiKeyObject2 ); + + // first call to find aggregates any AD_HOC_RUN_SAVED_OBJECT_TYPE SOs by apiKeyId internalSavedObjectsRepository.find.mockResolvedValueOnce({ saved_objects: [], total: 2, @@ -669,6 +812,18 @@ describe('Invalidate API Keys Task', () => { }, }, }); + + // second call to find aggregates any ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE SOs by apiKeyId + internalSavedObjectsRepository.find.mockResolvedValueOnce({ + saved_objects: [], + total: 2, + page: 1, + per_page: 10, + aggregations: { + apiKeyId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + }); + securityMockStart.authc.apiKeys.invalidateAsInternalUser.mockResolvedValue({ invalidated_api_keys: ['1'], previously_invalidated_api_keys: [], @@ -685,7 +840,7 @@ describe('Invalidate API Keys Task', () => { }); expect(result).toEqual(1); - expect(internalSavedObjectsRepository.find).toHaveBeenCalledTimes(2); + expect(internalSavedObjectsRepository.find).toHaveBeenCalledTimes(3); expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(1, { type: API_KEY_PENDING_INVALIDATION_TYPE, filter: `api_key_pending_invalidation.attributes.createdAt <= "1969-12-31T23:00:00.000Z"`, @@ -719,6 +874,152 @@ describe('Invalidate API Keys Task', () => { }, }, }); + expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(3, { + type: ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, + perPage: 0, + filter: `action_task_params.attributes.apiKeyId: "abcd====!" OR action_task_params.attributes.apiKeyId: "xyz!==!"`, + namespaces: ['*'], + aggs: { + apiKeyId: { + terms: { + field: `action_task_params.attributes.apiKeyId`, + size: 100, + }, + }, + }, + }); + expect(securityMockStart.authc.apiKeys.invalidateAsInternalUser).toHaveBeenCalledTimes(1); + expect(securityMockStart.authc.apiKeys.invalidateAsInternalUser).toHaveBeenCalledWith({ + ids: ['xyz!==!'], + }); + expect(internalSavedObjectsRepository.delete).toHaveBeenCalledTimes(1); + expect(internalSavedObjectsRepository.delete).toHaveBeenNthCalledWith( + 1, + API_KEY_PENDING_INVALIDATION_TYPE, + '2' + ); + expect(logger.debug).toHaveBeenCalledWith(`Total invalidated API keys "1"`); + }); + + test('should succeed when there are API keys to invalidate and API keys to exclude (ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE using apiKeyId)', async () => { + internalSavedObjectsRepository.find.mockResolvedValueOnce({ + saved_objects: [ + { + id: '1', + type: API_KEY_PENDING_INVALIDATION_TYPE, + score: 0, + attributes: { apiKeyId: 'encryptedencrypted', createdAt: '2024-04-11T17:08:44.035Z' }, + references: [], + }, + { + id: '2', + type: API_KEY_PENDING_INVALIDATION_TYPE, + score: 0, + attributes: { apiKeyId: 'encryptedencrypted', createdAt: '2024-04-11T17:08:44.035Z' }, + references: [], + }, + ], + total: 2, + per_page: 100, + page: 1, + }); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce( + mockInvalidatePendingApiKeyObject1 + ); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce( + mockInvalidatePendingApiKeyObject2 + ); + + // first call to find aggregates any AD_HOC_RUN_SAVED_OBJECT_TYPE SOs by apiKeyId + internalSavedObjectsRepository.find.mockResolvedValueOnce({ + saved_objects: [], + total: 2, + page: 1, + per_page: 10, + aggregations: { + apiKeyId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + }); + + // second call to find aggregates any ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE SOs by apiKeyId + internalSavedObjectsRepository.find.mockResolvedValueOnce({ + saved_objects: [], + total: 2, + page: 1, + per_page: 0, + aggregations: { + apiKeyId: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'abcd====!', doc_count: 1 }], + }, + }, + }); + + securityMockStart.authc.apiKeys.invalidateAsInternalUser.mockResolvedValue({ + invalidated_api_keys: ['1'], + previously_invalidated_api_keys: [], + error_count: 0, + }); + + const result = await runInvalidate({ + // @ts-expect-error + config: { invalidateApiKeysTask: { interval: '1m', removalDelay: '1h' } }, + encryptedSavedObjectsClient, + logger, + savedObjectsClient: internalSavedObjectsRepository, + security: securityMockStart, + }); + expect(result).toEqual(1); + + expect(internalSavedObjectsRepository.find).toHaveBeenCalledTimes(3); + expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(1, { + type: API_KEY_PENDING_INVALIDATION_TYPE, + filter: `api_key_pending_invalidation.attributes.createdAt <= "1969-12-31T23:00:00.000Z"`, + page: 1, + sortField: 'createdAt', + sortOrder: 'asc', + perPage: 100, + }); + expect(encryptedSavedObjectsClient.getDecryptedAsInternalUser).toHaveBeenCalledTimes(2); + expect(encryptedSavedObjectsClient.getDecryptedAsInternalUser).toHaveBeenNthCalledWith( + 1, + API_KEY_PENDING_INVALIDATION_TYPE, + '1' + ); + expect(encryptedSavedObjectsClient.getDecryptedAsInternalUser).toHaveBeenNthCalledWith( + 2, + API_KEY_PENDING_INVALIDATION_TYPE, + '2' + ); + expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(2, { + type: AD_HOC_RUN_SAVED_OBJECT_TYPE, + perPage: 0, + filter: `ad_hoc_run_params.attributes.apiKeyId: "abcd====!" OR ad_hoc_run_params.attributes.apiKeyId: "xyz!==!"`, + namespaces: ['*'], + aggs: { + apiKeyId: { + terms: { + field: `ad_hoc_run_params.attributes.apiKeyId`, + size: 100, + }, + }, + }, + }); + expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(3, { + type: ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, + perPage: 0, + filter: `action_task_params.attributes.apiKeyId: "abcd====!" OR action_task_params.attributes.apiKeyId: "xyz!==!"`, + namespaces: ['*'], + aggs: { + apiKeyId: { + terms: { + field: `action_task_params.attributes.apiKeyId`, + size: 100, + }, + }, + }, + }); expect(securityMockStart.authc.apiKeys.invalidateAsInternalUser).toHaveBeenCalledTimes(1); expect(securityMockStart.authc.apiKeys.invalidateAsInternalUser).toHaveBeenCalledWith({ ids: ['xyz!==!'], @@ -760,6 +1061,8 @@ describe('Invalidate API Keys Task', () => { encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce( mockInvalidatePendingApiKeyObject2 ); + + // first call to find aggregates any AD_HOC_RUN_SAVED_OBJECT_TYPE SOs by apiKeyId internalSavedObjectsRepository.find.mockResolvedValueOnce({ saved_objects: [], total: 2, @@ -777,6 +1080,21 @@ describe('Invalidate API Keys Task', () => { }, }); + // second call to find aggregates any ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE SOs by apiKeyId + internalSavedObjectsRepository.find.mockResolvedValueOnce({ + saved_objects: [], + total: 2, + page: 1, + per_page: 0, + aggregations: { + apiKeyId: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'abcd====!', doc_count: 3 }], + }, + }, + }); + const result = await runInvalidate({ // @ts-expect-error config: { invalidateApiKeysTask: { interval: '1m', removalDelay: '1h' } }, @@ -787,8 +1105,8 @@ describe('Invalidate API Keys Task', () => { }); expect(result).toEqual(0); - expect(internalSavedObjectsRepository.find).toHaveBeenCalledTimes(2); - expect(internalSavedObjectsRepository.find).toHaveBeenCalledWith({ + expect(internalSavedObjectsRepository.find).toHaveBeenCalledTimes(3); + expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(1, { type: API_KEY_PENDING_INVALIDATION_TYPE, filter: `api_key_pending_invalidation.attributes.createdAt <= "1969-12-31T23:00:00.000Z"`, page: 1, @@ -807,7 +1125,7 @@ describe('Invalidate API Keys Task', () => { API_KEY_PENDING_INVALIDATION_TYPE, '2' ); - expect(internalSavedObjectsRepository.find).toHaveBeenCalledWith({ + expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(2, { type: AD_HOC_RUN_SAVED_OBJECT_TYPE, perPage: 0, filter: `ad_hoc_run_params.attributes.apiKeyId: "abcd====!" OR ad_hoc_run_params.attributes.apiKeyId: "xyz!==!"`, @@ -821,6 +1139,20 @@ describe('Invalidate API Keys Task', () => { }, }, }); + expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(3, { + type: ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, + perPage: 0, + filter: `action_task_params.attributes.apiKeyId: "abcd====!" OR action_task_params.attributes.apiKeyId: "xyz!==!"`, + namespaces: ['*'], + aggs: { + apiKeyId: { + terms: { + field: `action_task_params.attributes.apiKeyId`, + size: 100, + }, + }, + }, + }); expect(securityMockStart.authc.apiKeys.invalidateAsInternalUser).not.toHaveBeenCalled(); expect(internalSavedObjectsRepository.delete).not.toHaveBeenCalled(); }); @@ -844,19 +1176,29 @@ describe('Invalidate API Keys Task', () => { encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce( mockInvalidatePendingApiKeyObject1 ); + + // first call to find aggregates any AD_HOC_RUN_SAVED_OBJECT_TYPE SOs by apiKeyId internalSavedObjectsRepository.find.mockResolvedValueOnce({ saved_objects: [], total: 2, page: 1, per_page: 0, aggregations: { - apiKeyId: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [], - }, + apiKeyId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, }, }); + + // second call to find aggregates any ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE SOs by apiKeyId + internalSavedObjectsRepository.find.mockResolvedValueOnce({ + saved_objects: [], + total: 2, + page: 1, + per_page: 0, + aggregations: { + apiKeyId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + }); + securityMockStart.authc.apiKeys.invalidateAsInternalUser.mockResolvedValue({ invalidated_api_keys: ['1'], previously_invalidated_api_keys: [], @@ -880,17 +1222,25 @@ describe('Invalidate API Keys Task', () => { encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce( mockInvalidatePendingApiKeyObject2 ); + // first call to find aggregates any AD_HOC_RUN_SAVED_OBJECT_TYPE SOs by apiKeyId internalSavedObjectsRepository.find.mockResolvedValueOnce({ saved_objects: [], total: 2, page: 1, per_page: 0, aggregations: { - apiKeyId: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [], - }, + apiKeyId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + }); + + // second call to find aggregates any ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE SOs by apiKeyId + internalSavedObjectsRepository.find.mockResolvedValueOnce({ + saved_objects: [], + total: 2, + page: 1, + per_page: 0, + aggregations: { + apiKeyId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, }, }); securityMockStart.authc.apiKeys.invalidateAsInternalUser.mockResolvedValue({ @@ -909,7 +1259,7 @@ describe('Invalidate API Keys Task', () => { }); expect(result).toEqual(2); - expect(internalSavedObjectsRepository.find).toHaveBeenCalledTimes(4); + expect(internalSavedObjectsRepository.find).toHaveBeenCalledTimes(6); expect(encryptedSavedObjectsClient.getDecryptedAsInternalUser).toHaveBeenCalledTimes(2); expect(securityMockStart.authc.apiKeys.invalidateAsInternalUser).toHaveBeenCalledTimes(2); expect(internalSavedObjectsRepository.delete).toHaveBeenCalledTimes(2); @@ -943,6 +1293,20 @@ describe('Invalidate API Keys Task', () => { }, }, }); + expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(3, { + type: ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, + perPage: 0, + filter: `action_task_params.attributes.apiKeyId: "abcd====!"`, + namespaces: ['*'], + aggs: { + apiKeyId: { + terms: { + field: `action_task_params.attributes.apiKeyId`, + size: 100, + }, + }, + }, + }); expect(securityMockStart.authc.apiKeys.invalidateAsInternalUser).toHaveBeenNthCalledWith(1, { ids: ['abcd====!'], }); @@ -954,7 +1318,7 @@ describe('Invalidate API Keys Task', () => { expect(logger.debug).toHaveBeenNthCalledWith(1, `Total invalidated API keys "1"`); // second iteration - expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(3, { + expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(4, { type: API_KEY_PENDING_INVALIDATION_TYPE, filter: `api_key_pending_invalidation.attributes.createdAt <= "1969-12-31T23:00:00.000Z"`, page: 1, @@ -967,7 +1331,7 @@ describe('Invalidate API Keys Task', () => { API_KEY_PENDING_INVALIDATION_TYPE, '2' ); - expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(4, { + expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(5, { type: AD_HOC_RUN_SAVED_OBJECT_TYPE, perPage: 0, filter: `ad_hoc_run_params.attributes.apiKeyId: "xyz!==!"`, @@ -981,6 +1345,20 @@ describe('Invalidate API Keys Task', () => { }, }, }); + expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(6, { + type: ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, + perPage: 0, + filter: `action_task_params.attributes.apiKeyId: "xyz!==!"`, + namespaces: ['*'], + aggs: { + apiKeyId: { + terms: { + field: `action_task_params.attributes.apiKeyId`, + size: 100, + }, + }, + }, + }); expect(securityMockStart.authc.apiKeys.invalidateAsInternalUser).toHaveBeenNthCalledWith(2, { ids: ['xyz!==!'], }); @@ -1021,6 +1399,7 @@ describe('Invalidate API Keys Task', () => { encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce( mockInvalidatePendingApiKeyObject2 ); + // first call to find aggregates any AD_HOC_RUN_SAVED_OBJECT_TYPE SOs by apiKeyId internalSavedObjectsRepository.find.mockResolvedValueOnce({ saved_objects: [], total: 2, @@ -1034,6 +1413,18 @@ describe('Invalidate API Keys Task', () => { }, }, }); + + // second call to find aggregates any ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE SOs by apiKeyId + internalSavedObjectsRepository.find.mockResolvedValueOnce({ + saved_objects: [], + total: 2, + page: 1, + per_page: 0, + aggregations: { + apiKeyId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + }); + securityMockStart.authc.apiKeys.invalidateAsInternalUser.mockResolvedValue({ invalidated_api_keys: ['1'], previously_invalidated_api_keys: [], @@ -1057,7 +1448,7 @@ describe('Invalidate API Keys Task', () => { }); expect(result).toEqual(1); - expect(internalSavedObjectsRepository.find).toHaveBeenCalledTimes(3); + expect(internalSavedObjectsRepository.find).toHaveBeenCalledTimes(4); expect(encryptedSavedObjectsClient.getDecryptedAsInternalUser).toHaveBeenCalledTimes(2); expect(securityMockStart.authc.apiKeys.invalidateAsInternalUser).toHaveBeenCalledTimes(1); expect(internalSavedObjectsRepository.delete).toHaveBeenCalledTimes(1); @@ -1096,6 +1487,20 @@ describe('Invalidate API Keys Task', () => { }, }, }); + expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(3, { + type: ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, + perPage: 0, + filter: `action_task_params.attributes.apiKeyId: "abcd====!" OR action_task_params.attributes.apiKeyId: "xyz!==!"`, + namespaces: ['*'], + aggs: { + apiKeyId: { + terms: { + field: `action_task_params.attributes.apiKeyId`, + size: 100, + }, + }, + }, + }); expect(securityMockStart.authc.apiKeys.invalidateAsInternalUser).toHaveBeenNthCalledWith(1, { ids: ['xyz!==!'], }); @@ -1107,7 +1512,7 @@ describe('Invalidate API Keys Task', () => { expect(logger.debug).toHaveBeenNthCalledWith(1, `Total invalidated API keys "1"`); // second iteration - expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(3, { + expect(internalSavedObjectsRepository.find).toHaveBeenNthCalledWith(4, { type: API_KEY_PENDING_INVALIDATION_TYPE, filter: `api_key_pending_invalidation.attributes.createdAt <= "1969-12-31T23:00:00.000Z" AND NOT api_key_pending_invalidation.id: "api_key_pending_invalidation:1"`, page: 1, diff --git a/x-pack/platform/plugins/shared/alerting/server/invalidate_pending_api_keys/task.ts b/x-pack/platform/plugins/shared/alerting/server/invalidate_pending_api_keys/task.ts index 48eea48246c78..b2e992623a643 100644 --- a/x-pack/platform/plugins/shared/alerting/server/invalidate_pending_api_keys/task.ts +++ b/x-pack/platform/plugins/shared/alerting/server/invalidate_pending_api_keys/task.ts @@ -21,7 +21,8 @@ import { import { AggregationsStringTermsBucketKeys, AggregationsTermsAggregateBase, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; +import { ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE } from '@kbn/actions-plugin/server/constants/saved_objects'; import { InvalidateAPIKeyResult } from '../rules_client'; import { AlertingConfig } from '../config'; import { timePeriodBeforeDate } from '../lib/get_cadence'; @@ -116,6 +117,7 @@ export function taskRunner( const savedObjectsClient = savedObjects.createInternalRepository([ API_KEY_PENDING_INVALIDATION_TYPE, AD_HOC_RUN_SAVED_OBJECT_TYPE, + ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, ]); const encryptedSavedObjectsClient = encryptedSavedObjects.getClient({ includedHiddenTypes: [API_KEY_PENDING_INVALIDATION_TYPE], @@ -248,29 +250,14 @@ export async function getApiKeyIdsToInvalidate({ ); // Query saved objects index to see if any API keys are in use - const filter = `${apiKeyIds - .map(({ apiKeyId }) => `${AD_HOC_RUN_SAVED_OBJECT_TYPE}.attributes.apiKeyId: "${apiKeyId}"`) - .join(' OR ')}`; - const { aggregations } = await savedObjectsClient.find< - AdHocRunSO, - { apiKeyId: AggregationsTermsAggregateBase } - >({ - type: AD_HOC_RUN_SAVED_OBJECT_TYPE, - filter, - perPage: 0, - namespaces: ['*'], - aggs: { - apiKeyId: { - terms: { - field: `${AD_HOC_RUN_SAVED_OBJECT_TYPE}.attributes.apiKeyId`, - size: PAGE_SIZE, - }, - }, - }, - }); + const apiKeyIdStrings = apiKeyIds.map(({ apiKeyId }) => apiKeyId); + let apiKeyIdsInUseBuckets: AggregationsStringTermsBucketKeys[] = []; - const apiKeyIdsInUseBuckets: AggregationsStringTermsBucketKeys[] = - (aggregations?.apiKeyId?.buckets as AggregationsStringTermsBucketKeys[]) ?? []; + for (const soType of [AD_HOC_RUN_SAVED_OBJECT_TYPE, ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE]) { + apiKeyIdsInUseBuckets = apiKeyIdsInUseBuckets.concat( + await queryForApiKeysInUse(apiKeyIdStrings, soType, savedObjectsClient) + ); + } const apiKeyIdsToInvalidate: ApiKeyIdAndSOId[] = []; const apiKeyIdsToExclude: ApiKeyIdAndSOId[] = []; @@ -335,3 +322,33 @@ export async function invalidateApiKeysAndDeletePendingApiKeySavedObject({ logger.debug(`Total invalidated API keys "${totalInvalidated}"`); return totalInvalidated; } + +async function queryForApiKeysInUse( + apiKeyIds: string[], + savedObjectType: string, + savedObjectsClient: SavedObjectsClientContract +): Promise { + const filter = `${apiKeyIds + .map((apiKeyId) => `${savedObjectType}.attributes.apiKeyId: "${apiKeyId}"`) + .join(' OR ')}`; + + const { aggregations } = await savedObjectsClient.find< + AdHocRunSO, + { apiKeyId: AggregationsTermsAggregateBase } + >({ + type: savedObjectType, + filter, + perPage: 0, + namespaces: ['*'], + aggs: { + apiKeyId: { + terms: { + field: `${savedObjectType}.attributes.apiKeyId`, + size: PAGE_SIZE, + }, + }, + }, + }); + + return (aggregations?.apiKeyId?.buckets as AggregationsStringTermsBucketKeys[]) ?? []; +} diff --git a/x-pack/platform/plugins/shared/alerting/server/lib/convert_es_sort_to_event_log_sort.ts b/x-pack/platform/plugins/shared/alerting/server/lib/convert_es_sort_to_event_log_sort.ts index 9adb2d0a21e69..b625791031d89 100644 --- a/x-pack/platform/plugins/shared/alerting/server/lib/convert_es_sort_to_event_log_sort.ts +++ b/x-pack/platform/plugins/shared/alerting/server/lib/convert_es_sort_to_event_log_sort.ts @@ -5,11 +5,7 @@ * 2.0. */ -import type { - Sort, - FieldSort, - SortCombinations, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { Sort, FieldSort, SortCombinations } from '@elastic/elasticsearch/lib/api/types'; const getFormattedSort = (sort: SortCombinations) => { if (typeof sort === 'string') { diff --git a/x-pack/platform/plugins/shared/alerting/server/lib/get_execution_log_aggregation.ts b/x-pack/platform/plugins/shared/alerting/server/lib/get_execution_log_aggregation.ts index 30f495efbf087..8f24c1acb5c12 100644 --- a/x-pack/platform/plugins/shared/alerting/server/lib/get_execution_log_aggregation.ts +++ b/x-pack/platform/plugins/shared/alerting/server/lib/get_execution_log_aggregation.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { KueryNode } from '@kbn/es-query'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import Boom from '@hapi/boom'; import { flatMap, get, isEmpty } from 'lodash'; import { AggregateEventsBySavedObjectResult } from '@kbn/event-log-plugin/server'; diff --git a/x-pack/platform/plugins/shared/alerting/server/lib/wrap_scoped_cluster_client.test.ts b/x-pack/platform/plugins/shared/alerting/server/lib/wrap_scoped_cluster_client.test.ts index e287712104949..1ed0d1ad7381f 100644 --- a/x-pack/platform/plugins/shared/alerting/server/lib/wrap_scoped_cluster_client.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/lib/wrap_scoped_cluster_client.test.ts @@ -11,7 +11,7 @@ import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; import { createWrappedScopedClusterClientFactory } from './wrap_scoped_cluster_client'; const esQuery = { - body: { query: { bool: { filter: { range: { '@timestamp': { gte: 0 } } } } } }, + query: { bool: { filter: { range: { '@timestamp': { gte: 0 } } } } }, }; const eqlQuery = { index: 'foo', @@ -20,9 +20,7 @@ const eqlQuery = { const esqlQueryRequest = { method: 'POST', path: '/_query', - body: { - query: 'from .kibana_task_manager', - }, + query: 'from .kibana_task_manager', }; let logger = loggingSystemMock.create().get(); @@ -73,7 +71,7 @@ describe('wrapScopedClusterClient', () => { expect(scopedClusterClient.asInternalUser.search).not.toHaveBeenCalled(); expect(scopedClusterClient.asCurrentUser.search).not.toHaveBeenCalled(); expect(loggingSystemMock.collect(logger).debug[0][0]).toEqual( - `executing query for rule .test-rule-type:abcdefg in space my-space - {\"body\":{\"query\":{\"bool\":{\"filter\":{\"range\":{\"@timestamp\":{\"gte\":0}}}}}}} - with options {} and 5000ms requestTimeout` + `executing query for rule .test-rule-type:abcdefg in space my-space - {\"query\":{\"bool\":{\"filter\":{\"range\":{\"@timestamp\":{\"gte\":0}}}}}} - with options {} and 5000ms requestTimeout` ); expect(loggingSystemMock.collect(logger).trace[0][0]).toEqual( `result of executing query for rule .test-rule-type:abcdefg in space my-space: {\"body\":{},\"statusCode\":200,\"headers\":{\"x-elastic-product\":\"Elasticsearch\"},\"warnings\":[],\"meta\":{}}` @@ -102,7 +100,7 @@ describe('wrapScopedClusterClient', () => { expect(scopedClusterClient.asInternalUser.search).not.toHaveBeenCalled(); expect(scopedClusterClient.asCurrentUser.search).not.toHaveBeenCalled(); expect(loggingSystemMock.collect(logger).debug[0][0]).toEqual( - `executing query for rule .test-rule-type:abcdefg in space my-space - {\"body\":{\"query\":{\"bool\":{\"filter\":{\"range\":{\"@timestamp\":{\"gte\":0}}}}}}} - with options {} and 5000ms requestTimeout` + `executing query for rule .test-rule-type:abcdefg in space my-space - {\"query\":{\"bool\":{\"filter\":{\"range\":{\"@timestamp\":{\"gte\":0}}}}}} - with options {} and 5000ms requestTimeout` ); expect(loggingSystemMock.collect(logger).trace[0][0]).toEqual( `result of executing query for rule .test-rule-type:abcdefg in space my-space: {\"body\":{},\"statusCode\":200,\"headers\":{\"x-elastic-product\":\"Elasticsearch\"},\"warnings\":[],\"meta\":{}}` @@ -136,7 +134,7 @@ describe('wrapScopedClusterClient', () => { expect(scopedClusterClient.asCurrentUser.search).not.toHaveBeenCalled(); expect(loggingSystemMock.collect(logger).debug[0][0]).toEqual( - `executing query for rule .test-rule-type:abcdefg in space my-space - {\"body\":{\"query\":{\"bool\":{\"filter\":{\"range\":{\"@timestamp\":{\"gte\":0}}}}}}} - with options {\"ignore\":[404],\"requestTimeout\":10000} and 5000ms requestTimeout` + `executing query for rule .test-rule-type:abcdefg in space my-space - {\"query\":{\"bool\":{\"filter\":{\"range\":{\"@timestamp\":{\"gte\":0}}}}}} - with options {\"ignore\":[404],\"requestTimeout\":10000} and 5000ms requestTimeout` ); expect(loggingSystemMock.collect(logger).trace[0][0]).toEqual( `result of executing query for rule .test-rule-type:abcdefg in space my-space: {\"body\":{},\"statusCode\":200,\"headers\":{\"x-elastic-product\":\"Elasticsearch\"},\"warnings\":[],\"meta\":{}}` @@ -161,11 +159,11 @@ describe('wrapScopedClusterClient', () => { ).rejects.toThrowErrorMatchingInlineSnapshot(`"something went wrong!"`); expect(loggingSystemMock.collect(logger).debug[0][0]).toEqual( - `executing query for rule .test-rule-type:abcdefg in space my-space - {\"body\":{\"query\":{\"bool\":{\"filter\":{\"range\":{\"@timestamp\":{\"gte\":0}}}}}}} - with options {}` + `executing query for rule .test-rule-type:abcdefg in space my-space - {\"query\":{\"bool\":{\"filter\":{\"range\":{\"@timestamp\":{\"gte\":0}}}}}} - with options {}` ); expect(logger.trace).not.toHaveBeenCalled(); expect(logger.warn).toHaveBeenCalledWith( - `executing query for rule .test-rule-type:abcdefg in space my-space - {\"body\":{\"query\":{\"bool\":{\"filter\":{\"range\":{\"@timestamp\":{\"gte\":0}}}}}}} - with options {}` + `executing query for rule .test-rule-type:abcdefg in space my-space - {\"query\":{\"bool\":{\"filter\":{\"range\":{\"@timestamp\":{\"gte\":0}}}}}} - with options {}` ); }); @@ -195,7 +193,7 @@ describe('wrapScopedClusterClient', () => { expect(stats.esSearchDurationMs).toEqual(0); expect(loggingSystemMock.collect(logger).debug[0][0]).toEqual( - `executing query for rule .test-rule-type:abcdefg in space my-space - {\"body\":{\"query\":{\"bool\":{\"filter\":{\"range\":{\"@timestamp\":{\"gte\":0}}}}}}} - with options {}` + `executing query for rule .test-rule-type:abcdefg in space my-space - {\"query\":{\"bool\":{\"filter\":{\"range\":{\"@timestamp\":{\"gte\":0}}}}}} - with options {}` ); expect(loggingSystemMock.collect(logger).trace[0][0]).toEqual( `result of executing query for rule .test-rule-type:abcdefg in space my-space: {}` @@ -230,7 +228,7 @@ describe('wrapScopedClusterClient', () => { expect(stats.esSearchDurationMs).toEqual(999); expect(loggingSystemMock.collect(logger).debug[0][0]).toEqual( - `executing query for rule .test-rule-type:abcdefg in space my-space - {\"body\":{\"query\":{\"bool\":{\"filter\":{\"range\":{\"@timestamp\":{\"gte\":0}}}}}}} - with options {}` + `executing query for rule .test-rule-type:abcdefg in space my-space - {\"query\":{\"bool\":{\"filter\":{\"range\":{\"@timestamp\":{\"gte\":0}}}}}} - with options {}` ); expect(loggingSystemMock.collect(logger).trace[0][0]).toEqual( `result of executing query for rule .test-rule-type:abcdefg in space my-space: {\"took\":333}` @@ -258,7 +256,7 @@ describe('wrapScopedClusterClient', () => { ); expect(loggingSystemMock.collect(logger).debug[0][0]).toEqual( - `executing query for rule .test-rule-type:abcdefg in space my-space - {\"body\":{\"query\":{\"bool\":{\"filter\":{\"range\":{\"@timestamp\":{\"gte\":0}}}}}}} - with options {}` + `executing query for rule .test-rule-type:abcdefg in space my-space - {\"query\":{\"bool\":{\"filter\":{\"range\":{\"@timestamp\":{\"gte\":0}}}}}} - with options {}` ); expect(logger.trace).not.toHaveBeenCalled(); expect(logger.warn).not.toHaveBeenCalled(); @@ -459,7 +457,7 @@ describe('wrapScopedClusterClient', () => { expect(scopedClusterClient.asCurrentUser.search).not.toHaveBeenCalled(); expect(loggingSystemMock.collect(logger).debug[0][0]).toEqual( - 'executing ES|QL query for rule .test-rule-type:abcdefg in space my-space - {"method":"POST","path":"/_query","body":{"query":"from .kibana_task_manager"}} - with options {} and 5000ms requestTimeout' + 'executing ES|QL query for rule .test-rule-type:abcdefg in space my-space - {"method":"POST","path":"/_query","query":"from .kibana_task_manager"} - with options {} and 5000ms requestTimeout' ); expect(logger.warn).not.toHaveBeenCalled(); }); @@ -485,7 +483,7 @@ describe('wrapScopedClusterClient', () => { expect(scopedClusterClient.asInternalUser.search).not.toHaveBeenCalled(); expect(scopedClusterClient.asCurrentUser.search).not.toHaveBeenCalled(); expect(loggingSystemMock.collect(logger).debug[0][0]).toEqual( - 'executing ES|QL query for rule .test-rule-type:abcdefg in space my-space - {"method":"POST","path":"/_query","body":{"query":"from .kibana_task_manager"}} - with options {} and 5000ms requestTimeout' + 'executing ES|QL query for rule .test-rule-type:abcdefg in space my-space - {"method":"POST","path":"/_query","query":"from .kibana_task_manager"} - with options {} and 5000ms requestTimeout' ); expect(logger.warn).not.toHaveBeenCalled(); }); @@ -516,7 +514,7 @@ describe('wrapScopedClusterClient', () => { expect(scopedClusterClient.asCurrentUser.search).not.toHaveBeenCalled(); expect(loggingSystemMock.collect(logger).debug[0][0]).toEqual( - 'executing ES|QL query for rule .test-rule-type:abcdefg in space my-space - {"method":"POST","path":"/_query","body":{"query":"from .kibana_task_manager"}} - with options {"ignore":[404],"requestTimeout":10000} and 5000ms requestTimeout' + 'executing ES|QL query for rule .test-rule-type:abcdefg in space my-space - {"method":"POST","path":"/_query","query":"from .kibana_task_manager"} - with options {"ignore":[404],"requestTimeout":10000} and 5000ms requestTimeout' ); expect(logger.warn).not.toHaveBeenCalled(); }); @@ -572,7 +570,7 @@ describe('wrapScopedClusterClient', () => { expect(stats.totalSearchDurationMs).toBeGreaterThan(-1); expect(loggingSystemMock.collect(logger).debug[0][0]).toEqual( - `executing ES|QL query for rule .test-rule-type:abcdefg in space my-space - {\"method\":\"POST\",\"path\":\"/_query\",\"body\":{\"query\":\"from .kibana_task_manager\"}} - with options {}` + `executing ES|QL query for rule .test-rule-type:abcdefg in space my-space - {\"method\":\"POST\",\"path\":\"/_query\",\"query\":\"from .kibana_task_manager\"} - with options {}` ); expect(logger.warn).not.toHaveBeenCalled(); }); diff --git a/x-pack/platform/plugins/shared/alerting/server/lib/wrap_scoped_cluster_client.ts b/x-pack/platform/plugins/shared/alerting/server/lib/wrap_scoped_cluster_client.ts index 3bf87b3653c5a..002895843bf48 100644 --- a/x-pack/platform/plugins/shared/alerting/server/lib/wrap_scoped_cluster_client.ts +++ b/x-pack/platform/plugins/shared/alerting/server/lib/wrap_scoped_cluster_client.ts @@ -23,7 +23,7 @@ import type { SearchRequest as SearchRequestWithBody, AggregationsAggregate, EqlSearchRequest as EqlSearchRequestWithBody, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import type { IScopedClusterClient, ElasticsearchClient, Logger } from '@kbn/core/server'; import { SearchMetrics, RuleInfo } from './types'; diff --git a/x-pack/platform/plugins/shared/alerting/server/monitoring/register_cluster_collector.ts b/x-pack/platform/plugins/shared/alerting/server/monitoring/register_cluster_collector.ts index 11832a5e5d00d..93fe8a44f1367 100644 --- a/x-pack/platform/plugins/shared/alerting/server/monitoring/register_cluster_collector.ts +++ b/x-pack/platform/plugins/shared/alerting/server/monitoring/register_cluster_collector.ts @@ -7,7 +7,7 @@ import type { AggregationsKeyedPercentiles, AggregationsPercentilesAggregateBase, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import { MonitoringCollectionSetup } from '@kbn/monitoring-collection-plugin/server'; import { aggregateTaskOverduePercentilesForType } from '@kbn/task-manager-plugin/server'; import { CoreSetup } from '@kbn/core/server'; diff --git a/x-pack/platform/plugins/shared/alerting/server/routes/backfill/apis/find/find_backfill_route.test.ts b/x-pack/platform/plugins/shared/alerting/server/routes/backfill/apis/find/find_backfill_route.test.ts index a8a0a210c8817..47d8e7c8f69aa 100644 --- a/x-pack/platform/plugins/shared/alerting/server/routes/backfill/apis/find/find_backfill_route.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/routes/backfill/apis/find/find_backfill_route.test.ts @@ -46,6 +46,7 @@ describe('findBackfillRoute', () => { tags: ['foo'], alertTypeId: 'myType', params: {}, + actions: [], apiKeyOwner: 'user', apiKeyCreatedByUser: false, consumer: 'myApp', @@ -73,6 +74,7 @@ describe('findBackfillRoute', () => { tags: ['foo'], alertTypeId: 'myType', params: {}, + actions: [], apiKeyOwner: 'user', apiKeyCreatedByUser: false, consumer: 'myApp', diff --git a/x-pack/platform/plugins/shared/alerting/server/routes/backfill/apis/get/get_backfill_route.test.ts b/x-pack/platform/plugins/shared/alerting/server/routes/backfill/apis/get/get_backfill_route.test.ts index 79ac8df1ed4b5..6b7aafbc14e86 100644 --- a/x-pack/platform/plugins/shared/alerting/server/routes/backfill/apis/get/get_backfill_route.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/routes/backfill/apis/get/get_backfill_route.test.ts @@ -35,6 +35,7 @@ describe('getBackfillRoute', () => { tags: ['foo'], alertTypeId: 'myType', params: {}, + actions: [], apiKeyOwner: 'user', apiKeyCreatedByUser: false, consumer: 'myApp', diff --git a/x-pack/platform/plugins/shared/alerting/server/routes/backfill/apis/schedule/schedule_backfill_route.test.ts b/x-pack/platform/plugins/shared/alerting/server/routes/backfill/apis/schedule/schedule_backfill_route.test.ts index c08cca6dfe683..670f86671ff8b 100644 --- a/x-pack/platform/plugins/shared/alerting/server/routes/backfill/apis/schedule/schedule_backfill_route.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/routes/backfill/apis/schedule/schedule_backfill_route.test.ts @@ -44,6 +44,7 @@ describe('scheduleBackfillRoute', () => { tags: ['foo'], alertTypeId: 'myType', params: {}, + actions: [], apiKeyOwner: 'user', apiKeyCreatedByUser: false, consumer: 'myApp', @@ -71,6 +72,7 @@ describe('scheduleBackfillRoute', () => { tags: ['foo'], alertTypeId: 'myType', params: {}, + actions: [], apiKeyOwner: 'user', apiKeyCreatedByUser: false, consumer: 'myApp', diff --git a/x-pack/platform/plugins/shared/alerting/server/routes/backfill/apis/schedule/transforms/transform_request/v1.ts b/x-pack/platform/plugins/shared/alerting/server/routes/backfill/apis/schedule/transforms/transform_request/v1.ts index 170d85c4f862b..83e8a6e82c5ca 100644 --- a/x-pack/platform/plugins/shared/alerting/server/routes/backfill/apis/schedule/transforms/transform_request/v1.ts +++ b/x-pack/platform/plugins/shared/alerting/server/routes/backfill/apis/schedule/transforms/transform_request/v1.ts @@ -10,4 +10,9 @@ import { ScheduleBackfillRequestBodyV1 } from '../../../../../../../common/route import { ScheduleBackfillParams } from '../../../../../../application/backfill/methods/schedule/types'; export const transformRequest = (request: ScheduleBackfillRequestBodyV1): ScheduleBackfillParams => - request.map(({ rule_id, start, end }) => ({ ruleId: rule_id, start, end })); + request.map(({ rule_id, start, end, run_actions }) => ({ + ruleId: rule_id, + start, + end, + runActions: run_actions, + })); diff --git a/x-pack/platform/plugins/shared/alerting/server/routes/backfill/transforms/transform_backfill_to_backfill_response/v1.test.ts b/x-pack/platform/plugins/shared/alerting/server/routes/backfill/transforms/transform_backfill_to_backfill_response/v1.test.ts index 88582bea15b92..fe4a0c96e6d4f 100644 --- a/x-pack/platform/plugins/shared/alerting/server/routes/backfill/transforms/transform_backfill_to_backfill_response/v1.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/routes/backfill/transforms/transform_backfill_to_backfill_response/v1.test.ts @@ -19,6 +19,7 @@ describe('transformBackfillToBackfillResponse', () => { tags: ['foo'], alertTypeId: 'myType', params: {}, + actions: [], apiKeyOwner: 'user', apiKeyCreatedByUser: false, consumer: 'myApp', @@ -49,6 +50,7 @@ describe('transformBackfillToBackfillResponse', () => { name: 'my rule name', tags: ['foo'], rule_type_id: 'myType', + actions: [], params: {}, api_key_owner: 'user', api_key_created_by_user: false, diff --git a/x-pack/platform/plugins/shared/alerting/server/routes/suggestions/values_suggestion_alerts.ts b/x-pack/platform/plugins/shared/alerting/server/routes/suggestions/values_suggestion_alerts.ts index 5ad7e7a8ac437..e9364df87b11c 100644 --- a/x-pack/platform/plugins/shared/alerting/server/routes/suggestions/values_suggestion_alerts.ts +++ b/x-pack/platform/plugins/shared/alerting/server/routes/suggestions/values_suggestion_alerts.ts @@ -12,7 +12,7 @@ import { getRequestAbortedSignal } from '@kbn/data-plugin/server'; import { termsAggSuggestions } from '@kbn/unified-search-plugin/server/autocomplete/terms_agg'; import type { ConfigSchema } from '@kbn/unified-search-plugin/server/config'; import { getKbnServerError, reportServerError } from '@kbn/kibana-utils-plugin/server'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { ALERT_RULE_CONSUMER, ALERT_RULE_TYPE_ID, SPACE_IDS } from '@kbn/rule-data-utils'; import { verifyAccessAndContext } from '../lib'; diff --git a/x-pack/platform/plugins/shared/alerting/server/routes/suggestions/values_suggestion_rules.ts b/x-pack/platform/plugins/shared/alerting/server/routes/suggestions/values_suggestion_rules.ts index 1f33cba025396..cb8d2d3a29c9d 100644 --- a/x-pack/platform/plugins/shared/alerting/server/routes/suggestions/values_suggestion_rules.ts +++ b/x-pack/platform/plugins/shared/alerting/server/routes/suggestions/values_suggestion_rules.ts @@ -14,7 +14,7 @@ import type { ConfigSchema } from '@kbn/unified-search-plugin/server/config'; import { UsageCounter } from '@kbn/usage-collection-plugin/server'; import { getKbnServerError, reportServerError } from '@kbn/kibana-utils-plugin/server'; import { ALERTING_CASES_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server/src/saved_objects_index_pattern'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { verifyAccessAndContext } from '../lib'; import { ILicenseState } from '../../lib'; diff --git a/x-pack/platform/plugins/shared/alerting/server/rules_client/lib/denormalize_actions.ts b/x-pack/platform/plugins/shared/alerting/server/rules_client/lib/denormalize_actions.ts index 3cd1113a13628..ed27fe651ea11 100644 --- a/x-pack/platform/plugins/shared/alerting/server/rules_client/lib/denormalize_actions.ts +++ b/x-pack/platform/plugins/shared/alerting/server/rules_client/lib/denormalize_actions.ts @@ -5,25 +5,21 @@ * 2.0. */ import { SavedObjectReference } from '@kbn/core/server'; +import { ActionsClient } from '@kbn/actions-plugin/server'; import { preconfiguredConnectorActionRefPrefix, systemConnectorActionRefPrefix, } from '../common/constants'; -import { - DenormalizedAction, - NormalizedAlertActionWithGeneratedValues, - RulesClientContext, -} from '../types'; +import { DenormalizedAction, NormalizedAlertActionWithGeneratedValues } from '../types'; export async function denormalizeActions( - context: RulesClientContext, + actionsClient: ActionsClient, alertActions: NormalizedAlertActionWithGeneratedValues[] ): Promise<{ actions: DenormalizedAction[]; references: SavedObjectReference[] }> { const references: SavedObjectReference[] = []; const actions: DenormalizedAction[] = []; if (alertActions.length) { - const actionsClient = await context.getActionsClient(); const actionIds = [...new Set(alertActions.map((alertAction) => alertAction.id))]; const actionResults = await actionsClient.getBulk({ diff --git a/x-pack/platform/plugins/shared/alerting/server/rules_client/lib/extract_references.ts b/x-pack/platform/plugins/shared/alerting/server/rules_client/lib/extract_references.ts index 9dfca0897ca08..6a131e9ee9179 100644 --- a/x-pack/platform/plugins/shared/alerting/server/rules_client/lib/extract_references.ts +++ b/x-pack/platform/plugins/shared/alerting/server/rules_client/lib/extract_references.ts @@ -26,7 +26,11 @@ export async function extractReferences< params: ExtractedParams; references: SavedObjectReference[]; }> { - const { references: actionReferences, actions } = await denormalizeActions(context, ruleActions); + const actionsClient = await context.getActionsClient(); + const { references: actionReferences, actions } = await denormalizeActions( + actionsClient, + ruleActions + ); // Extracts any references using configured reference extractor if available const extractedRefsAndParams = ruleType?.useSavedObjectReferences?.extractReferences diff --git a/x-pack/platform/plugins/shared/alerting/server/rules_client/methods/get_action_error_log.ts b/x-pack/platform/plugins/shared/alerting/server/rules_client/methods/get_action_error_log.ts index 4d71af6573b57..41c161071b1c5 100644 --- a/x-pack/platform/plugins/shared/alerting/server/rules_client/methods/get_action_error_log.ts +++ b/x-pack/platform/plugins/shared/alerting/server/rules_client/methods/get_action_error_log.ts @@ -6,7 +6,7 @@ */ import { KueryNode } from '@kbn/es-query'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { SanitizedRuleWithLegacyId } from '../../types'; import { convertEsSortToEventLogSort } from '../../lib'; import { diff --git a/x-pack/platform/plugins/shared/alerting/server/rules_client/methods/get_execution_log.ts b/x-pack/platform/plugins/shared/alerting/server/rules_client/methods/get_execution_log.ts index 95d41a02a685b..457dc33064229 100644 --- a/x-pack/platform/plugins/shared/alerting/server/rules_client/methods/get_execution_log.ts +++ b/x-pack/platform/plugins/shared/alerting/server/rules_client/methods/get_execution_log.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { KueryNode } from '@kbn/es-query'; import { SanitizedRuleWithLegacyId } from '../../types'; import { diff --git a/x-pack/platform/plugins/shared/alerting/server/rules_client/tests/get_execution_log.test.ts b/x-pack/platform/plugins/shared/alerting/server/rules_client/tests/get_execution_log.test.ts index 3a3f801dd9085..11882f1ea176f 100644 --- a/x-pack/platform/plugins/shared/alerting/server/rules_client/tests/get_execution_log.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/rules_client/tests/get_execution_log.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { RulesClient, ConstructorOptions } from '../rules_client'; import { savedObjectsClientMock, diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/action_scheduler.test.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/action_scheduler.test.ts index c0eb08e6d582f..c77d7efd96864 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/action_scheduler.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/action_scheduler.test.ts @@ -18,7 +18,11 @@ import { InjectActionParamsOpts, injectActionParams } from '../inject_action_par import { RuleTypeParams, SanitizedRule, GetViewInAppRelativeUrlFnOpts } from '../../types'; import { RuleRunMetricsStore } from '../../lib/rule_run_metrics_store'; import { alertingEventLoggerMock } from '../../lib/alerting_event_logger/alerting_event_logger.mock'; -import { ConcreteTaskInstance, TaskErrorSource } from '@kbn/task-manager-plugin/server'; +import { + ConcreteTaskInstance, + TaskErrorSource, + TaskPriority, +} from '@kbn/task-manager-plugin/server'; import { RuleNotifyWhen } from '../../../common'; import { asSavedObjectExecutionSource } from '@kbn/actions-plugin/server'; import sinon from 'sinon'; @@ -116,6 +120,7 @@ describe('Action Scheduler', () => { Object { "actionTypeId": "test", "apiKey": "MTIzOmFiYw==", + "apiKeyId": undefined, "consumer": "rule-consumer", "executionId": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", "id": "1", @@ -125,6 +130,7 @@ describe('Action Scheduler', () => { "foo": true, "stateVal": "My goes here", }, + "priority": undefined, "relatedSavedObjects": Array [ Object { "id": "1", @@ -366,6 +372,7 @@ describe('Action Scheduler', () => { Object { "actionTypeId": "test", "apiKey": "MTIzOmFiYw==", + "apiKeyId": undefined, "consumer": "rule-consumer", "executionId": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", "id": "1", @@ -375,6 +382,7 @@ describe('Action Scheduler', () => { "foo": true, "stateVal": "My goes here", }, + "priority": undefined, "relatedSavedObjects": Array [ Object { "id": "1", @@ -411,6 +419,7 @@ describe('Action Scheduler', () => { Object { "actionTypeId": "test", "apiKey": "MTIzOmFiYw==", + "apiKeyId": undefined, "consumer": "rule-consumer", "executionId": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", "id": "1", @@ -420,6 +429,7 @@ describe('Action Scheduler', () => { "foo": true, "stateVal": "My state-val goes here", }, + "priority": undefined, "relatedSavedObjects": Array [ Object { "id": "1", @@ -769,6 +779,7 @@ describe('Action Scheduler', () => { Object { "actionTypeId": "test", "apiKey": "MTIzOmFiYw==", + "apiKeyId": undefined, "consumer": "rule-consumer", "executionId": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", "id": "action-2", @@ -778,6 +789,7 @@ describe('Action Scheduler', () => { "foo": true, "stateVal": "My goes here", }, + "priority": undefined, "relatedSavedObjects": Array [ Object { "id": "1", @@ -1014,12 +1026,14 @@ describe('Action Scheduler', () => { Object { "actionTypeId": "testActionTypeId", "apiKey": "MTIzOmFiYw==", + "apiKeyId": undefined, "consumer": "rule-consumer", "executionId": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", "id": "1", "params": Object { "message": "New: 1 Ongoing: 0 Recovered: 0", }, + "priority": undefined, "relatedSavedObjects": Array [ Object { "id": "1", @@ -1161,12 +1175,14 @@ describe('Action Scheduler', () => { Object { "actionTypeId": "testActionTypeId", "apiKey": "MTIzOmFiYw==", + "apiKeyId": undefined, "consumer": "rule-consumer", "executionId": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", "id": "1", "params": Object { "message": "New: 1 Ongoing: 0 Recovered: 0", }, + "priority": undefined, "relatedSavedObjects": Array [ Object { "id": "1", @@ -1413,6 +1429,7 @@ describe('Action Scheduler', () => { Object { "actionTypeId": "test", "apiKey": "MTIzOmFiYw==", + "apiKeyId": undefined, "consumer": "rule-consumer", "executionId": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", "id": "1", @@ -1422,6 +1439,7 @@ describe('Action Scheduler', () => { "foo": true, "stateVal": "My goes here", }, + "priority": undefined, "relatedSavedObjects": Array [ Object { "id": "1", @@ -1443,6 +1461,7 @@ describe('Action Scheduler', () => { Object { "actionTypeId": "test", "apiKey": "MTIzOmFiYw==", + "apiKeyId": undefined, "consumer": "rule-consumer", "executionId": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", "id": "2", @@ -1452,6 +1471,7 @@ describe('Action Scheduler', () => { "foo": true, "stateVal": "My goes here", }, + "priority": undefined, "relatedSavedObjects": Array [ Object { "id": "1", @@ -1974,6 +1994,154 @@ describe('Action Scheduler', () => { Object { "actionTypeId": "test", "apiKey": "MTIzOmFiYw==", + "apiKeyId": undefined, + "consumer": "rule-consumer", + "executionId": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + "id": "1", + "params": Object { + "alertVal": "My 1 name-of-alert test1 tag-A,tag-B 1 goes here", + "contextVal": "My goes here", + "foo": true, + "stateVal": "My goes here", + }, + "priority": undefined, + "relatedSavedObjects": Array [ + Object { + "id": "1", + "namespace": "test1", + "type": "alert", + "typeId": "test", + }, + ], + "source": Object { + "source": Object { + "id": "1", + "type": "alert", + }, + "type": "SAVED_OBJECT", + }, + "spaceId": "test1", + "uuid": "111-111", + }, + Object { + "actionTypeId": "test", + "apiKey": "MTIzOmFiYw==", + "apiKeyId": undefined, + "consumer": "rule-consumer", + "executionId": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + "id": "1", + "params": Object { + "alertVal": "My 1 name-of-alert test1 tag-A,tag-B 2 goes here", + "contextVal": "My goes here", + "foo": true, + "stateVal": "My goes here", + }, + "priority": undefined, + "relatedSavedObjects": Array [ + Object { + "id": "1", + "namespace": "test1", + "type": "alert", + "typeId": "test", + }, + ], + "source": Object { + "source": Object { + "id": "1", + "type": "alert", + }, + "type": "SAVED_OBJECT", + }, + "spaceId": "test1", + "uuid": "111-111", + }, + Object { + "actionTypeId": "test", + "apiKey": "MTIzOmFiYw==", + "apiKeyId": undefined, + "consumer": "rule-consumer", + "executionId": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + "id": "1", + "params": Object { + "alertVal": "My 1 name-of-alert test1 tag-A,tag-B 3 goes here", + "contextVal": "My goes here", + "foo": true, + "stateVal": "My goes here", + }, + "priority": undefined, + "relatedSavedObjects": Array [ + Object { + "id": "1", + "namespace": "test1", + "type": "alert", + "typeId": "test", + }, + ], + "source": Object { + "source": Object { + "id": "1", + "type": "alert", + }, + "type": "SAVED_OBJECT", + }, + "spaceId": "test1", + "uuid": "111-111", + }, + ], + ] + `); + }); + + test('does schedule actions with priority when specified', async () => { + const actionScheduler = new ActionScheduler( + getSchedulerContext({ + ...defaultSchedulerContext, + priority: TaskPriority.Low, + rule: { + ...defaultSchedulerContext.rule, + actions: [ + { + ...defaultSchedulerContext.rule.actions[0], + frequency: { + summary: false, + notifyWhen: RuleNotifyWhen.CHANGE, + throttle: null, + }, + }, + ], + }, + }) + ); + + await actionScheduler.run({ + activeCurrentAlerts: { + ...generateAlert({ + id: 1, + pendingRecoveredCount: 1, + lastScheduledActionsGroup: 'recovered', + }), + ...generateAlert({ + id: 2, + pendingRecoveredCount: 1, + lastScheduledActionsGroup: 'recovered', + }), + ...generateAlert({ + id: 3, + pendingRecoveredCount: 1, + lastScheduledActionsGroup: 'recovered', + }), + }, + recoveredCurrentAlerts: {}, + }); + + expect(actionsClient.bulkEnqueueExecution).toHaveBeenCalledTimes(1); + expect(actionsClient.bulkEnqueueExecution.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Array [ + Object { + "actionTypeId": "test", + "apiKey": "MTIzOmFiYw==", + "apiKeyId": undefined, "consumer": "rule-consumer", "executionId": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", "id": "1", @@ -1983,6 +2151,7 @@ describe('Action Scheduler', () => { "foo": true, "stateVal": "My goes here", }, + "priority": 1, "relatedSavedObjects": Array [ Object { "id": "1", @@ -2004,6 +2173,7 @@ describe('Action Scheduler', () => { Object { "actionTypeId": "test", "apiKey": "MTIzOmFiYw==", + "apiKeyId": undefined, "consumer": "rule-consumer", "executionId": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", "id": "1", @@ -2013,6 +2183,7 @@ describe('Action Scheduler', () => { "foo": true, "stateVal": "My goes here", }, + "priority": 1, "relatedSavedObjects": Array [ Object { "id": "1", @@ -2034,6 +2205,7 @@ describe('Action Scheduler', () => { Object { "actionTypeId": "test", "apiKey": "MTIzOmFiYw==", + "apiKeyId": undefined, "consumer": "rule-consumer", "executionId": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", "id": "1", @@ -2043,6 +2215,7 @@ describe('Action Scheduler', () => { "foo": true, "stateVal": "My goes here", }, + "priority": 1, "relatedSavedObjects": Array [ Object { "id": "1", @@ -2523,6 +2696,7 @@ describe('Action Scheduler', () => { Object { "actionTypeId": ".test-system-action", "apiKey": "MTIzOmFiYw==", + "apiKeyId": undefined, "consumer": "rule-consumer", "executionId": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", "id": "1", @@ -2530,6 +2704,7 @@ describe('Action Scheduler', () => { "foo": "bar", "myParams": "test", }, + "priority": undefined, "relatedSavedObjects": Array [ Object { "id": "1", diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/lib/build_rule_url.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/lib/build_rule_url.ts index 3df27a512c7f9..3f828709ee940 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/lib/build_rule_url.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/lib/build_rule_url.ts @@ -6,16 +6,17 @@ */ import { Logger } from '@kbn/logging'; -import { RuleTypeParams, SanitizedRule } from '@kbn/alerting-types'; +import { RuleTypeParams } from '@kbn/alerting-types'; import { getRuleDetailsRoute, triggersActionsRoute } from '@kbn/rule-data-utils'; import { GetViewInAppRelativeUrlFn } from '../../../types'; +import { ActionSchedulerRule } from '../types'; interface BuildRuleUrlOpts { end?: number; getViewInAppRelativeUrl?: GetViewInAppRelativeUrlFn; kibanaBaseUrl: string | undefined; logger: Logger; - rule: SanitizedRule; + rule: ActionSchedulerRule; spaceId: string; start?: number; } diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/lib/format_action_to_enqueue.test.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/lib/format_action_to_enqueue.test.ts index 02ff513c5b639..8afcc95c11fff 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/lib/format_action_to_enqueue.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/lib/format_action_to_enqueue.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { TaskPriority } from '@kbn/task-manager-plugin/server'; import { RULE_SAVED_OBJECT_TYPE } from '../../..'; import { formatActionToEnqueue } from './format_action_to_enqueue'; @@ -65,6 +66,124 @@ describe('formatActionToEnqueue', () => { }); }); + test('should format a rule action with priority as expected', () => { + expect( + formatActionToEnqueue({ + action: { + id: '1', + group: 'default', + actionTypeId: 'test', + params: { + foo: true, + contextVal: 'My {{context.value}} goes here', + stateVal: 'My {{state.value}} goes here', + alertVal: + 'My {{rule.id}} {{rule.name}} {{rule.spaceId}} {{rule.tags}} {{alert.id}} goes here', + }, + uuid: '111-111', + }, + apiKey: 'MTIzOmFiYw==', + executionId: '123', + ruleConsumer: 'rule-consumer', + ruleId: 'aaa', + ruleTypeId: 'security-rule', + spaceId: 'default', + priority: TaskPriority.Low, + }) + ).toEqual({ + id: '1', + uuid: '111-111', + params: { + foo: true, + contextVal: 'My {{context.value}} goes here', + stateVal: 'My {{state.value}} goes here', + alertVal: + 'My {{rule.id}} {{rule.name}} {{rule.spaceId}} {{rule.tags}} {{alert.id}} goes here', + }, + spaceId: 'default', + apiKey: 'MTIzOmFiYw==', + consumer: 'rule-consumer', + source: { + source: { + id: 'aaa', + type: RULE_SAVED_OBJECT_TYPE, + }, + type: 'SAVED_OBJECT', + }, + executionId: '123', + relatedSavedObjects: [ + { + id: 'aaa', + type: RULE_SAVED_OBJECT_TYPE, + namespace: undefined, + typeId: 'security-rule', + }, + ], + actionTypeId: 'test', + priority: 1, + }); + }); + + test('should format a rule action with apiKeyId as expected', () => { + expect( + formatActionToEnqueue({ + action: { + id: '1', + group: 'default', + actionTypeId: 'test', + params: { + foo: true, + contextVal: 'My {{context.value}} goes here', + stateVal: 'My {{state.value}} goes here', + alertVal: + 'My {{rule.id}} {{rule.name}} {{rule.spaceId}} {{rule.tags}} {{alert.id}} goes here', + }, + uuid: '111-111', + }, + apiKey: 'MTIzOmFiYw==', + apiKeyId: '4534623462346', + executionId: '123', + ruleConsumer: 'rule-consumer', + ruleId: 'aaa', + ruleTypeId: 'security-rule', + spaceId: 'default', + priority: TaskPriority.Low, + }) + ).toEqual({ + id: '1', + uuid: '111-111', + params: { + foo: true, + contextVal: 'My {{context.value}} goes here', + stateVal: 'My {{state.value}} goes here', + alertVal: + 'My {{rule.id}} {{rule.name}} {{rule.spaceId}} {{rule.tags}} {{alert.id}} goes here', + }, + spaceId: 'default', + apiKey: 'MTIzOmFiYw==', + consumer: 'rule-consumer', + source: { + source: { + id: 'aaa', + type: RULE_SAVED_OBJECT_TYPE, + }, + type: 'SAVED_OBJECT', + }, + executionId: '123', + relatedSavedObjects: [ + { + id: 'aaa', + type: RULE_SAVED_OBJECT_TYPE, + namespace: undefined, + typeId: 'security-rule', + }, + ], + actionTypeId: 'test', + priority: 1, + apiKeyId: '4534623462346', + }); + }); + test('should format a rule action with null apiKey as expected', () => { expect( formatActionToEnqueue({ diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/lib/format_action_to_enqueue.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/lib/format_action_to_enqueue.ts index af560a19ab9be..763d653688085 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/lib/format_action_to_enqueue.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/lib/format_action_to_enqueue.ts @@ -7,12 +7,15 @@ import { RuleAction, RuleSystemAction } from '@kbn/alerting-types'; import { asSavedObjectExecutionSource } from '@kbn/actions-plugin/server'; +import { TaskPriority } from '@kbn/task-manager-plugin/server'; import { RULE_SAVED_OBJECT_TYPE } from '../../..'; interface FormatActionToEnqueueOpts { action: RuleAction | RuleSystemAction; + apiKeyId?: string; apiKey: string | null; executionId: string; + priority?: TaskPriority; ruleConsumer: string; ruleId: string; ruleTypeId: string; @@ -20,7 +23,17 @@ interface FormatActionToEnqueueOpts { } export const formatActionToEnqueue = (opts: FormatActionToEnqueueOpts) => { - const { action, apiKey, executionId, ruleConsumer, ruleId, ruleTypeId, spaceId } = opts; + const { + action, + apiKey, + apiKeyId, + executionId, + priority, + ruleConsumer, + ruleId, + ruleTypeId, + spaceId, + } = opts; const namespace = spaceId === 'default' ? {} : { namespace: spaceId }; return { @@ -29,6 +42,7 @@ export const formatActionToEnqueue = (opts: FormatActionToEnqueueOpts) => { params: action.params, spaceId, apiKey: apiKey ?? null, + apiKeyId, consumer: ruleConsumer, source: asSavedObjectExecutionSource({ id: ruleId, @@ -44,5 +58,6 @@ export const formatActionToEnqueue = (opts: FormatActionToEnqueueOpts) => { }, ], actionTypeId: action.actionTypeId, + priority, }; }; diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/per_alert_action_scheduler.test.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/per_alert_action_scheduler.test.ts index 62e501f6963af..91bfc0d4d0fa1 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/per_alert_action_scheduler.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/per_alert_action_scheduler.test.ts @@ -22,6 +22,7 @@ import { AlertInstanceContext, AlertInstanceState, } from '@kbn/alerting-state-types'; +import { TaskPriority } from '@kbn/task-manager-plugin/server'; const alertingEventLogger = alertingEventLoggerMock.create(); const actionsClient = actionsClientMock.create(); @@ -91,7 +92,13 @@ const getSchedulerContext = (params = {}) => { return { ...defaultSchedulerContext, rule, ...params, ruleRunMetricsStore }; }; -const getResult = (actionId: string, alertId: string, actionUuid: string) => ({ +const getResult = ( + actionId: string, + alertId: string, + actionUuid: string, + priority?: number, + apiKeyId?: string +) => ({ actionToEnqueue: { actionTypeId: 'test', apiKey: 'MTIzOmFiYw==', @@ -102,6 +109,8 @@ const getResult = (actionId: string, alertId: string, actionUuid: string) => ({ relatedSavedObjects: [{ id: 'rule-id-1', namespace: 'test1', type: 'alert', typeId: 'test' }], source: { source: { id: 'rule-id-1', type: 'alert' }, type: 'SAVED_OBJECT' }, spaceId: 'test1', + ...(priority ? { priority } : {}), + ...(apiKeyId ? { apiKeyId } : {}), }, actionToLog: { alertGroup: 'default', alertId, id: actionId, uuid: actionUuid, typeId: 'test' }, }); @@ -236,6 +245,64 @@ describe('Per-Alert Action Scheduler', () => { ]); }); + test('test should create action to schedule with priority if specified for each alert and each action', async () => { + // 2 per-alert actions * 2 alerts = 4 actions to schedule + const scheduler = new PerAlertActionScheduler({ + ...getSchedulerContext(), + priority: TaskPriority.Low, + }); + const results = await scheduler.getActionsToSchedule({ + activeCurrentAlerts: alerts, + }); + + expect(alertsClient.getSummarizedAlerts).not.toHaveBeenCalled(); + expect(logger.debug).not.toHaveBeenCalled(); + + expect(ruleRunMetricsStore.getNumberOfGeneratedActions()).toEqual(4); + expect(ruleRunMetricsStore.getNumberOfTriggeredActions()).toEqual(4); + expect(ruleRunMetricsStore.getStatusByConnectorType('test')).toEqual({ + numberOfGeneratedActions: 4, + numberOfTriggeredActions: 4, + }); + + expect(results).toHaveLength(4); + expect(results).toEqual([ + getResult('action-1', '1', '111-111', 1), + getResult('action-1', '2', '111-111', 1), + getResult('action-2', '1', '222-222', 1), + getResult('action-2', '2', '222-222', 1), + ]); + }); + + test('test should create action to schedule with apiKeyId if specified for each alert and each action', async () => { + // 2 per-alert actions * 2 alerts = 4 actions to schedule + const scheduler = new PerAlertActionScheduler({ + ...getSchedulerContext(), + apiKeyId: '23534ybfsdsnsdf', + }); + const results = await scheduler.getActionsToSchedule({ + activeCurrentAlerts: alerts, + }); + + expect(alertsClient.getSummarizedAlerts).not.toHaveBeenCalled(); + expect(logger.debug).not.toHaveBeenCalled(); + + expect(ruleRunMetricsStore.getNumberOfGeneratedActions()).toEqual(4); + expect(ruleRunMetricsStore.getNumberOfTriggeredActions()).toEqual(4); + expect(ruleRunMetricsStore.getStatusByConnectorType('test')).toEqual({ + numberOfGeneratedActions: 4, + numberOfTriggeredActions: 4, + }); + + expect(results).toHaveLength(4); + expect(results).toEqual([ + getResult('action-1', '1', '111-111', undefined, '23534ybfsdsnsdf'), + getResult('action-1', '2', '111-111', undefined, '23534ybfsdsnsdf'), + getResult('action-2', '1', '222-222', undefined, '23534ybfsdsnsdf'), + getResult('action-2', '2', '222-222', undefined, '23534ybfsdsnsdf'), + ]); + }); + test('should skip creating actions to schedule when alert has maintenance window', async () => { // 2 per-alert actions * 2 alerts = 4 actions to schedule // but alert 1 has maintenance window, so only actions for alert 2 should be scheduled diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/per_alert_action_scheduler.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/per_alert_action_scheduler.ts index 28b35d885b3d2..0ad9422b7b69d 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/per_alert_action_scheduler.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/per_alert_action_scheduler.ts @@ -240,7 +240,9 @@ export class PerAlertActionScheduler< actionToEnqueue: formatActionToEnqueue({ action: actionToRun, apiKey: this.context.apiKey, + apiKeyId: this.context.apiKeyId, executionId: this.context.executionId, + priority: this.context.priority, ruleConsumer: this.context.ruleConsumer, ruleId: this.context.rule.id, ruleTypeId: this.context.ruleType.id, diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/summary_action_scheduler.test.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/summary_action_scheduler.test.ts index cb19cb781ae3e..87356cdbacdaa 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/summary_action_scheduler.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/summary_action_scheduler.test.ts @@ -28,6 +28,7 @@ import { } from '@kbn/task-manager-plugin/server/task_running/errors'; import { CombinedSummarizedAlerts } from '../../../types'; import { ActionsCompletion } from '@kbn/alerting-state-types'; +import { TaskPriority } from '@kbn/task-manager-plugin/server'; const alertingEventLogger = alertingEventLoggerMock.create(); const actionsClient = actionsClientMock.create(); @@ -97,7 +98,13 @@ const getSchedulerContext = (params = {}) => { return { ...defaultSchedulerContext, rule, ...params, ruleRunMetricsStore }; }; -const getResult = (actionId: string, actionUuid: string, summary: CombinedSummarizedAlerts) => ({ +const getResult = ( + actionId: string, + actionUuid: string, + summary: CombinedSummarizedAlerts, + priority?: number, + apiKeyId?: string +) => ({ actionToEnqueue: { actionTypeId: 'test', apiKey: 'MTIzOmFiYw==', @@ -108,6 +115,8 @@ const getResult = (actionId: string, actionUuid: string, summary: CombinedSummar relatedSavedObjects: [{ id: 'rule-id-1', namespace: 'test1', type: 'alert', typeId: 'test' }], source: { source: { id: 'rule-id-1', type: 'alert' }, type: 'SAVED_OBJECT' }, spaceId: 'test1', + ...(priority && { priority }), + ...(apiKeyId && { apiKeyId }), }, actionToLog: { alertSummary: { @@ -261,6 +270,108 @@ describe('Summary Action Scheduler', () => { ]); }); + test('should create action to schedule with priority if specified for summary action when summary action is per rule run', async () => { + alertsClient.getProcessedAlerts.mockReturnValue(alerts); + const summarizedAlerts = { + new: { count: 2, data: [mockAAD, mockAAD] }, + ongoing: { count: 0, data: [] }, + recovered: { count: 0, data: [] }, + }; + alertsClient.getSummarizedAlerts.mockResolvedValue(summarizedAlerts); + + const throttledSummaryActions = {}; + const scheduler = new SummaryActionScheduler({ + ...getSchedulerContext(), + priority: TaskPriority.Low, + }); + const results = await scheduler.getActionsToSchedule({ + activeCurrentAlerts: alerts, + throttledSummaryActions, + }); + + expect(throttledSummaryActions).toEqual({}); + expect(alertsClient.getSummarizedAlerts).toHaveBeenCalledTimes(2); + expect(alertsClient.getSummarizedAlerts).toHaveBeenNthCalledWith(1, { + excludedAlertInstanceIds: [], + executionUuid: defaultSchedulerContext.executionId, + ruleId: 'rule-id-1', + spaceId: 'test1', + }); + expect(alertsClient.getSummarizedAlerts).toHaveBeenNthCalledWith(2, { + excludedAlertInstanceIds: [], + executionUuid: defaultSchedulerContext.executionId, + ruleId: 'rule-id-1', + spaceId: 'test1', + }); + expect(logger.debug).not.toHaveBeenCalled(); + + expect(ruleRunMetricsStore.getNumberOfGeneratedActions()).toEqual(2); + expect(ruleRunMetricsStore.getNumberOfTriggeredActions()).toEqual(2); + expect(ruleRunMetricsStore.getStatusByConnectorType('test')).toEqual({ + numberOfGeneratedActions: 2, + numberOfTriggeredActions: 2, + }); + + expect(results).toHaveLength(2); + + const finalSummary = { ...summarizedAlerts, all: { count: 2, data: [mockAAD, mockAAD] } }; + expect(results).toEqual([ + getResult('action-2', '222-222', finalSummary, 1), + getResult('action-3', '333-333', finalSummary, 1), + ]); + }); + + test('should create action to schedule with apiKeyId if specified for summary action when summary action is per rule run', async () => { + alertsClient.getProcessedAlerts.mockReturnValue(alerts); + const summarizedAlerts = { + new: { count: 2, data: [mockAAD, mockAAD] }, + ongoing: { count: 0, data: [] }, + recovered: { count: 0, data: [] }, + }; + alertsClient.getSummarizedAlerts.mockResolvedValue(summarizedAlerts); + + const throttledSummaryActions = {}; + const scheduler = new SummaryActionScheduler({ + ...getSchedulerContext(), + apiKeyId: '24534wy3wydfbs', + }); + const results = await scheduler.getActionsToSchedule({ + activeCurrentAlerts: alerts, + throttledSummaryActions, + }); + + expect(throttledSummaryActions).toEqual({}); + expect(alertsClient.getSummarizedAlerts).toHaveBeenCalledTimes(2); + expect(alertsClient.getSummarizedAlerts).toHaveBeenNthCalledWith(1, { + excludedAlertInstanceIds: [], + executionUuid: defaultSchedulerContext.executionId, + ruleId: 'rule-id-1', + spaceId: 'test1', + }); + expect(alertsClient.getSummarizedAlerts).toHaveBeenNthCalledWith(2, { + excludedAlertInstanceIds: [], + executionUuid: defaultSchedulerContext.executionId, + ruleId: 'rule-id-1', + spaceId: 'test1', + }); + expect(logger.debug).not.toHaveBeenCalled(); + + expect(ruleRunMetricsStore.getNumberOfGeneratedActions()).toEqual(2); + expect(ruleRunMetricsStore.getNumberOfTriggeredActions()).toEqual(2); + expect(ruleRunMetricsStore.getStatusByConnectorType('test')).toEqual({ + numberOfGeneratedActions: 2, + numberOfTriggeredActions: 2, + }); + + expect(results).toHaveLength(2); + + const finalSummary = { ...summarizedAlerts, all: { count: 2, data: [mockAAD, mockAAD] } }; + expect(results).toEqual([ + getResult('action-2', '222-222', finalSummary, undefined, '24534wy3wydfbs'), + getResult('action-3', '333-333', finalSummary, undefined, '24534wy3wydfbs'), + ]); + }); + test('should create actions to schedule for summary action when summary action has alertsFilter', async () => { alertsClient.getProcessedAlerts.mockReturnValue(alerts); const summarizedAlerts = { diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/summary_action_scheduler.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/summary_action_scheduler.ts index db53f15be2180..a606819f93af8 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/summary_action_scheduler.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/summary_action_scheduler.ts @@ -206,7 +206,9 @@ export class SummaryActionScheduler< actionToEnqueue: formatActionToEnqueue({ action: actionToRun, apiKey: this.context.apiKey, + apiKeyId: this.context.apiKeyId, executionId: this.context.executionId, + priority: this.context.priority, ruleConsumer: this.context.ruleConsumer, ruleId: this.context.rule.id, ruleTypeId: this.context.ruleType.id, diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/system_action_scheduler.test.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/system_action_scheduler.test.ts index 71a7584c7280b..153af5f2051e9 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/system_action_scheduler.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/system_action_scheduler.test.ts @@ -27,6 +27,7 @@ import { } from '@kbn/task-manager-plugin/server/task_running/errors'; import { CombinedSummarizedAlerts } from '../../../types'; import { schema } from '@kbn/config-schema'; +import { TaskPriority } from '@kbn/task-manager-plugin/server'; const alertingEventLogger = alertingEventLoggerMock.create(); const actionsClient = actionsClientMock.create(); @@ -68,7 +69,13 @@ const getSchedulerContext = (params = {}) => { return { ...defaultSchedulerContext, rule, ...params, ruleRunMetricsStore }; }; -const getResult = (actionId: string, actionUuid: string, summary: CombinedSummarizedAlerts) => ({ +const getResult = ( + actionId: string, + actionUuid: string, + summary: CombinedSummarizedAlerts, + priority?: number, + apiKeyId?: string +) => ({ actionToEnqueue: { actionTypeId: '.test-system-action', apiKey: 'MTIzOmFiYw==', @@ -79,6 +86,8 @@ const getResult = (actionId: string, actionUuid: string, summary: CombinedSummar relatedSavedObjects: [{ id: 'rule-id-1', namespace: 'test1', type: 'alert', typeId: 'test' }], source: { source: { id: 'rule-id-1', type: 'alert' }, type: 'SAVED_OBJECT' }, spaceId: 'test1', + ...(priority && { priority }), + ...(apiKeyId && { apiKeyId }), }, actionToLog: { alertSummary: { @@ -183,6 +192,82 @@ describe('System Action Scheduler', () => { expect(results).toEqual([getResult('system-action-1', 'xxx-xxx', finalSummary)]); }); + test('should create actions to schedule with priority if specified for each system action', async () => { + alertsClient.getProcessedAlerts.mockReturnValue(alerts); + + const summarizedAlerts = { + new: { count: 2, data: [mockAAD, mockAAD] }, + ongoing: { count: 0, data: [] }, + recovered: { count: 0, data: [] }, + }; + alertsClient.getSummarizedAlerts.mockResolvedValue(summarizedAlerts); + + const scheduler = new SystemActionScheduler({ + ...getSchedulerContext(), + priority: TaskPriority.Low, + }); + const results = await scheduler.getActionsToSchedule({}); + + expect(alertsClient.getSummarizedAlerts).toHaveBeenCalledTimes(1); + expect(alertsClient.getSummarizedAlerts).toHaveBeenCalledWith({ + excludedAlertInstanceIds: [], + executionUuid: defaultSchedulerContext.executionId, + ruleId: 'rule-id-1', + spaceId: 'test1', + }); + + expect(ruleRunMetricsStore.getNumberOfGeneratedActions()).toEqual(1); + expect(ruleRunMetricsStore.getNumberOfTriggeredActions()).toEqual(1); + expect(ruleRunMetricsStore.getStatusByConnectorType('.test-system-action')).toEqual({ + numberOfGeneratedActions: 1, + numberOfTriggeredActions: 1, + }); + + expect(results).toHaveLength(1); + + const finalSummary = { ...summarizedAlerts, all: { count: 2, data: [mockAAD, mockAAD] } }; + expect(results).toEqual([getResult('system-action-1', 'xxx-xxx', finalSummary, 1)]); + }); + + test('should create actions to schedule with apiKeyId if specified for each system action', async () => { + alertsClient.getProcessedAlerts.mockReturnValue(alerts); + + const summarizedAlerts = { + new: { count: 2, data: [mockAAD, mockAAD] }, + ongoing: { count: 0, data: [] }, + recovered: { count: 0, data: [] }, + }; + alertsClient.getSummarizedAlerts.mockResolvedValue(summarizedAlerts); + + const scheduler = new SystemActionScheduler({ + ...getSchedulerContext(), + apiKeyId: '464tfbwer5q43h', + }); + const results = await scheduler.getActionsToSchedule({}); + + expect(alertsClient.getSummarizedAlerts).toHaveBeenCalledTimes(1); + expect(alertsClient.getSummarizedAlerts).toHaveBeenCalledWith({ + excludedAlertInstanceIds: [], + executionUuid: defaultSchedulerContext.executionId, + ruleId: 'rule-id-1', + spaceId: 'test1', + }); + + expect(ruleRunMetricsStore.getNumberOfGeneratedActions()).toEqual(1); + expect(ruleRunMetricsStore.getNumberOfTriggeredActions()).toEqual(1); + expect(ruleRunMetricsStore.getStatusByConnectorType('.test-system-action')).toEqual({ + numberOfGeneratedActions: 1, + numberOfTriggeredActions: 1, + }); + + expect(results).toHaveLength(1); + + const finalSummary = { ...summarizedAlerts, all: { count: 2, data: [mockAAD, mockAAD] } }; + expect(results).toEqual([ + getResult('system-action-1', 'xxx-xxx', finalSummary, undefined, '464tfbwer5q43h'), + ]); + }); + test('should remove new alerts from summary if suppressed by maintenance window', async () => { const newAlertWithMaintenanceWindow = generateAlert({ id: 1, diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/system_action_scheduler.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/system_action_scheduler.ts index 0c5cceb0f0a52..01be6e4202ec8 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/system_action_scheduler.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/schedulers/system_action_scheduler.ts @@ -156,7 +156,9 @@ export class SystemActionScheduler< actionToEnqueue: formatActionToEnqueue({ action: actionToRun, apiKey: this.context.apiKey, + apiKeyId: this.context.apiKeyId, executionId: this.context.executionId, + priority: this.context.priority, ruleConsumer: this.context.ruleConsumer, ruleId: this.context.rule.id, ruleTypeId: this.context.ruleType.id, diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/types.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/types.ts index 02b9647f91866..d14c871aa4f61 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/types.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/action_scheduler/types.ts @@ -9,6 +9,7 @@ import type { Logger } from '@kbn/core/server'; import { PublicMethodsOf } from '@kbn/utility-types'; import { ActionsClient } from '@kbn/actions-plugin/server/actions_client'; import { ExecuteOptions as EnqueueExecutionOptions } from '@kbn/actions-plugin/server/create_execute_function'; +import { TaskPriority } from '@kbn/task-manager-plugin/server'; import { IAlertsClient } from '../../alerts_client/types'; import { Alert } from '../../alert'; import { @@ -31,6 +32,10 @@ import { } from '../../lib/alerting_event_logger/alerting_event_logger'; import { RuleTaskInstance, TaskRunnerContext } from '../types'; +export type ActionSchedulerRule = Omit< + SanitizedRule, + 'executionStatus' +>; export interface ActionSchedulerOptions< Params extends RuleTypeParams, ExtractedParams extends RuleTypeParams, @@ -53,10 +58,11 @@ export interface ActionSchedulerOptions< >; logger: Logger; alertingEventLogger: PublicMethodsOf; - rule: SanitizedRule; + rule: ActionSchedulerRule; taskRunnerContext: TaskRunnerContext; taskInstance: RuleTaskInstance; ruleRunMetricsStore: RuleRunMetricsStore; + apiKeyId?: string; apiKey: RawRule['apiKey']; ruleConsumer: string; executionId: string; @@ -64,6 +70,7 @@ export interface ActionSchedulerOptions< previousStartedAt: Date | null; actionsClient: PublicMethodsOf; alertsClient: IAlertsClient; + priority?: TaskPriority; } export type Executable< diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/ad_hoc_task_runner.test.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/ad_hoc_task_runner.test.ts index ae6467d0dcbf8..ba9d78a7f3c9b 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/ad_hoc_task_runner.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/ad_hoc_task_runner.test.ts @@ -7,7 +7,7 @@ import sinon from 'sinon'; import { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; -import { actionsMock } from '@kbn/actions-plugin/server/mocks'; +import { actionsClientMock, actionsMock } from '@kbn/actions-plugin/server/mocks'; import { SavedObject } from '@kbn/core/server'; import { elasticsearchServiceMock, @@ -25,7 +25,7 @@ import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/s import { IEventLogger } from '@kbn/event-log-plugin/server'; import { eventLoggerMock } from '@kbn/event-log-plugin/server/mocks'; import { SharePluginStart } from '@kbn/share-plugin/server'; -import { ConcreteTaskInstance, TaskStatus } from '@kbn/task-manager-plugin/server'; +import { ConcreteTaskInstance, TaskPriority, TaskStatus } from '@kbn/task-manager-plugin/server'; import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; import { AdHocTaskRunner } from './ad_hoc_task_runner'; import { TaskRunnerContext } from './types'; @@ -39,7 +39,7 @@ import { import { AdHocRunSchedule, AdHocRunSO } from '../data/ad_hoc_run/types'; import { AD_HOC_RUN_SAVED_OBJECT_TYPE, RULE_SAVED_OBJECT_TYPE } from '../saved_objects'; import { adHocRunStatus } from '../../common/constants'; -import { DATE_1970, ruleType } from './fixtures'; +import { DATE_1970, generateEnqueueFunctionInput, mockAAD, ruleType } from './fixtures'; import { alertingEventLoggerMock } from '../lib/alerting_event_logger/alerting_event_logger.mock'; import { alertsMock } from '../mocks'; import { UntypedNormalizedRuleType } from '../rule_type_registry'; @@ -93,6 +93,8 @@ import { RuleRunMetricsStore } from '../lib/rule_run_metrics_store'; import { ConnectorAdapterRegistry } from '../connector_adapters/connector_adapter_registry'; import { rulesSettingsServiceMock } from '../rules_settings/rules_settings_service.mock'; import { maintenanceWindowsServiceMock } from './maintenance_windows/maintenance_windows_service.mock'; +import { alertsClientMock } from '../alerts_client/alerts_client.mock'; +import { alertsServiceMock } from '../alerts_service/alerts_service.mock'; const UUID = '5f6aa57d-3e22-484e-bae8-cbed868f4d28'; @@ -121,7 +123,7 @@ type TaskRunnerFactoryInitializerParamsType = jest.Mocked & { executionContext: ReturnType; }; const clusterClient = elasticsearchServiceMock.createClusterClient().asInternalUser; - +const mockAlertsService = alertsServiceMock.create(); const alertingEventLogger = alertingEventLoggerMock.create(); const elasticsearchAndSOAvailability$ = of(true); const alertsService = new AlertsService({ @@ -133,6 +135,8 @@ const alertsService = new AlertsService({ elasticsearchAndSOAvailability$, isServerless: false, }); +const alertsClient = alertsClientMock.create(); +const actionsClient = actionsClientMock.create(); const backfillClient = backfillClientMock.create(); const dataPlugin = dataPluginMock.createStartContract(); const dataViewsMock = { @@ -280,7 +284,7 @@ describe('Ad Hoc Task Runner', () => { name: 'test', tags: [], alertTypeId: 'siem.queryRule', - // @ts-expect-error + actions: [], params: { author: [], description: 'test', @@ -367,10 +371,22 @@ describe('Ad Hoc Task Runner', () => { taskRunnerFactoryInitializerParams.executionContext.withContext.mockImplementation((ctx, fn) => fn() ); + taskRunnerFactoryInitializerParams.actionsPlugin.getActionsClientWithRequest.mockResolvedValue( + actionsClient + ); + taskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue(true); + taskRunnerFactoryInitializerParams.actionsPlugin.renderActionParameterTemplates.mockImplementation( + (_, __, params) => params + ); + maintenanceWindowsService.getMaintenanceWindows.mockResolvedValue({ + maintenanceWindows: [], + maintenanceWindowsWithoutScopedQueryIds: [], + }); ruleTypeRegistry.get.mockReturnValue(ruleTypeWithAlerts); ruleTypeWithAlerts.executor.mockResolvedValue({ state: {} }); mockValidateRuleTypeParams.mockReturnValue(mockedAdHocRunSO.attributes.rule.params); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedAdHocRunSO); + actionsClient.bulkEnqueueExecution.mockResolvedValue({ errors: false, items: [] }); }); afterAll(() => fakeTimer.restore()); @@ -461,7 +477,7 @@ describe('Ad Hoc Task Runner', () => { index: '.alerts-test.alerts-default', refresh: 'wait_for', require_alias: !useDataStreamForAlerts, - body: [ + operations: [ { create: { _id: UUID, @@ -541,6 +557,127 @@ describe('Ad Hoc Task Runner', () => { expect(logger.error).not.toHaveBeenCalled(); }); + test('should schedule actions for rule with actions', async () => { + const mockedAdHocRunSOWithActions = { + ...mockedAdHocRunSO, + attributes: { + ...mockedAdHocRunSO.attributes, + rule: { + ...mockedAdHocRunSO.attributes.rule, + id: '1', + actions: [ + { + uuid: '123abc', + group: 'default', + actionRef: 'action_0', + actionTypeId: 'action', + params: { foo: true }, + frequency: { + notifyWhen: 'onActiveAlert', + summary: true, + throttle: null, + }, + }, + ], + }, + }, + references: [ + { type: RULE_SAVED_OBJECT_TYPE, name: 'rule', id: '1' }, + { id: '4', name: 'action_0', type: 'action' }, + ], + }; + alertsClient.getProcessedAlerts.mockReturnValue({}); + alertsClient.getSummarizedAlerts.mockResolvedValue({ + new: { count: 1, data: [mockAAD] }, + ongoing: { count: 0, data: [] }, + recovered: { count: 0, data: [] }, + }); + mockAlertsService.createAlertsClient.mockImplementation(() => alertsClient); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue( + mockedAdHocRunSOWithActions + ); + + ruleTypeWithAlerts.executor.mockImplementation( + async ({ + services: executorServices, + }: RuleExecutorOptions< + RuleTypeParams, + RuleTypeState, + AlertInstanceState, + AlertInstanceContext, + string, + RuleAlertData + >) => { + executorServices.alertsClient?.report({ + id: '1', + actionGroup: 'default', + payload: { textField: 'foo', numericField: 27 }, + }); + return { state: {} }; + } + ); + + const taskRunner = new AdHocTaskRunner({ + context: { ...taskRunnerFactoryInitializerParams, alertsService: mockAlertsService }, + internalSavedObjectsRepository, + taskInstance: mockedTaskInstance, + }); + expect(AlertingEventLogger).toHaveBeenCalledTimes(1); + + const runnerResult = await taskRunner.run(); + expect(runnerResult).toEqual({ state: {}, runAt: new Date('1970-01-01T00:00:00.000Z') }); + await taskRunner.cleanup(); + + // Verify all the expected calls were made before calling the rule executor + expect(encryptedSavedObjectsClient.getDecryptedAsInternalUser).toHaveBeenCalledWith( + AD_HOC_RUN_SAVED_OBJECT_TYPE, + 'abc', + {} + ); + expect(ruleTypeRegistry.ensureRuleTypeEnabled).toHaveBeenCalledWith('siem.queryRule'); + expect(mockValidateRuleTypeParams).toHaveBeenCalledWith( + mockedAdHocRunSO.attributes.rule.params, + ruleTypeWithAlerts.validate.params + ); + // @ts-ignore - accessing private variable + // should run the first entry in the schedule + expect(taskRunner.scheduleToRunIndex).toEqual(0); + + // Verify all the expected calls were made while calling the rule executor + expect(RuleRunMetricsStore).toHaveBeenCalledTimes(1); + expect(ruleTypeWithAlerts.executor).toHaveBeenCalledTimes(1); + + expect(internalSavedObjectsRepository.update).toHaveBeenCalledWith( + AD_HOC_RUN_SAVED_OBJECT_TYPE, + mockedAdHocRunSO.id, + { + schedule: [ + { ...schedule1, status: adHocRunStatus.COMPLETE }, + schedule2, + schedule3, + schedule4, + schedule5, + ], + }, + { namespace: undefined, refresh: false } + ); + + expect(internalSavedObjectsRepository.delete).not.toHaveBeenCalled(); + + expect(actionsClient.bulkEnqueueExecution).toHaveBeenCalledTimes(1); + expect(actionsClient.bulkEnqueueExecution).toHaveBeenCalledWith( + generateEnqueueFunctionInput({ + isBulk: true, + id: '4', + foo: true, + consumer: 'siem', + uuid: '123abc', + priority: TaskPriority.Low, + apiKeyId: 'apiKeyId', + }) + ); + }); + test('should run with the next pending schedule', async () => { ruleTypeWithAlerts.executor.mockImplementation( async ({ @@ -608,13 +745,13 @@ describe('Ad Hoc Task Runner', () => { const bulkCall = clusterClient.bulk.mock.calls[0][0]; // @ts-ignore - expect(bulkCall.body[1][TIMESTAMP]).toEqual(schedule4.runAt); + expect(bulkCall.operations[1][TIMESTAMP]).toEqual(schedule4.runAt); // @ts-ignore - expect(bulkCall.body[1][ALERT_START]).toEqual(schedule4.runAt); + expect(bulkCall.operations[1][ALERT_START]).toEqual(schedule4.runAt); // @ts-ignore - expect(bulkCall.body[1][ALERT_TIME_RANGE]).toEqual({ gte: schedule4.runAt }); + expect(bulkCall.operations[1][ALERT_TIME_RANGE]).toEqual({ gte: schedule4.runAt }); // @ts-ignore - expect(bulkCall.body[1][ALERT_RULE_EXECUTION_TIMESTAMP]).toEqual(DATE_1970); + expect(bulkCall.operations[1][ALERT_RULE_EXECUTION_TIMESTAMP]).toEqual(DATE_1970); expect(internalSavedObjectsRepository.update).toHaveBeenCalledWith( AD_HOC_RUN_SAVED_OBJECT_TYPE, @@ -715,13 +852,13 @@ describe('Ad Hoc Task Runner', () => { const bulkCall = clusterClient.bulk.mock.calls[0][0]; // @ts-ignore - expect(bulkCall.body[1][TIMESTAMP]).toEqual(schedule5.runAt); + expect(bulkCall.operations[1][TIMESTAMP]).toEqual(schedule5.runAt); // @ts-ignore - expect(bulkCall.body[1][ALERT_START]).toEqual(schedule5.runAt); + expect(bulkCall.operations[1][ALERT_START]).toEqual(schedule5.runAt); // @ts-ignore - expect(bulkCall.body[1][ALERT_TIME_RANGE]).toEqual({ gte: schedule5.runAt }); + expect(bulkCall.operations[1][ALERT_TIME_RANGE]).toEqual({ gte: schedule5.runAt }); // @ts-ignore - expect(bulkCall.body[1][ALERT_RULE_EXECUTION_TIMESTAMP]).toEqual(DATE_1970); + expect(bulkCall.operations[1][ALERT_RULE_EXECUTION_TIMESTAMP]).toEqual(DATE_1970); expect(internalSavedObjectsRepository.update).toHaveBeenCalledWith( AD_HOC_RUN_SAVED_OBJECT_TYPE, diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/ad_hoc_task_runner.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/ad_hoc_task_runner.ts index c9932820ff808..7eff959b05c2b 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/ad_hoc_task_runner.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/ad_hoc_task_runner.ts @@ -20,7 +20,7 @@ import { TaskErrorSource, } from '@kbn/task-manager-plugin/server'; import { nanosToMillis } from '@kbn/event-log-plugin/common'; -import { CancellableTask, RunResult } from '@kbn/task-manager-plugin/server/task'; +import { CancellableTask, RunResult, TaskPriority } from '@kbn/task-manager-plugin/server/task'; import { AdHocRunStatus, adHocRunStatus } from '../../common/constants'; import { RuleRunnerErrorStackTraceLog, RuleTaskStateAndMetrics, TaskRunnerContext } from './types'; import { getExecutorServices } from './get_executor_services'; @@ -35,7 +35,7 @@ import { RuleTypeState, } from '../types'; import { TaskRunnerTimer, TaskRunnerTimerSpan } from './task_runner_timer'; -import { AdHocRun, AdHocRunSchedule, AdHocRunSO } from '../data/ad_hoc_run/types'; +import { AdHocRun, AdHocRunSO, AdHocRunSchedule } from '../data/ad_hoc_run/types'; import { AD_HOC_RUN_SAVED_OBJECT_TYPE } from '../saved_objects'; import { RuleMonitoringService } from '../monitoring/rule_monitoring_service'; import { AdHocTaskRunningHandler } from './ad_hoc_task_running_handler'; @@ -52,6 +52,8 @@ import { import { RuleRunMetrics, RuleRunMetricsStore } from '../lib/rule_run_metrics_store'; import { getEsErrorMessage } from '../lib/errors'; import { Result, isOk, asOk, asErr } from '../lib/result_type'; +import { ActionScheduler } from './action_scheduler'; +import { transformAdHocRunToAdHocRunData } from '../application/backfill/transforms/transform_ad_hoc_run_to_backfill_result'; interface ConstructorParams { context: TaskRunnerContext; @@ -173,7 +175,7 @@ export class AdHocTaskRunner implements CancellableTask { return ruleRunMetricsStore.getMetrics(); } - const { rule } = adHocRunData; + const { rule, apiKeyToUse, apiKeyId } = adHocRunData; const ruleType = this.ruleTypeRegistry.get(rule.alertTypeId); const ruleLabel = `${ruleType.id}:${rule.id}: '${rule.name}'`; @@ -254,6 +256,36 @@ export class AdHocTaskRunner implements CancellableTask { throw error; } + const actionScheduler = new ActionScheduler({ + rule: { + ...rule, + muteAll: false, + mutedInstanceIds: [], + createdAt: new Date(rule.createdAt), + updatedAt: new Date(rule.updatedAt), + }, + ruleType, + logger: this.logger, + taskRunnerContext: this.context, + taskInstance: this.taskInstance, + ruleRunMetricsStore, + apiKey: apiKeyToUse, + apiKeyId, + ruleConsumer: rule.consumer, + executionId: this.executionId, + ruleLabel, + previousStartedAt: null, + alertingEventLogger: this.alertingEventLogger, + actionsClient: await this.context.actionsPlugin.getActionsClientWithRequest(fakeRequest), + alertsClient, + priority: TaskPriority.Low, + }); + + await actionScheduler.run({ + activeCurrentAlerts: alertsClient.getProcessedAlerts('activeCurrent'), + recoveredCurrentAlerts: alertsClient.getProcessedAlerts('recoveredCurrent'), + }); + return ruleRunMetricsStore.getMetrics(); } @@ -299,14 +331,12 @@ export class AdHocTaskRunner implements CancellableTask { { namespace } ); - adHocRunData = { - id: adHocRunSO.id, - ...adHocRunSO.attributes, - rule: { - ...adHocRunSO.attributes.rule, - id: adHocRunSO.references[0].id, - }, - }; + adHocRunData = transformAdHocRunToAdHocRunData({ + adHocRunSO, + isSystemAction: (connectorId: string) => + this.context.actionsPlugin.isSystemActionConnector(connectorId), + omitGeneratedActionValues: false, + }); } catch (err) { const errorSource = SavedObjectsErrorHelpers.isNotFoundError(err) ? TaskErrorSource.USER diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/fixtures.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/fixtures.ts index d820f2690caeb..090c633b79602 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/fixtures.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/fixtures.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { TaskStatus } from '@kbn/task-manager-plugin/server'; +import { TaskPriority, TaskStatus } from '@kbn/task-manager-plugin/server'; import { SavedObject } from '@kbn/core/server'; import { ALERTING_CASES_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; import { @@ -408,14 +408,20 @@ export const generateEnqueueFunctionInput = ({ isBulk = false, isResolved, foo, + consumer, actionTypeId, + priority, + apiKeyId, }: { uuid?: string; id: string; isBulk?: boolean; isResolved?: boolean; foo?: boolean; + consumer?: string; actionTypeId?: string; + priority?: TaskPriority; + apiKeyId?: string; }) => { const input = { actionTypeId: actionTypeId || 'action', @@ -427,7 +433,7 @@ export const generateEnqueueFunctionInput = ({ ...(isResolved !== undefined ? { isResolved } : {}), ...(foo !== undefined ? { foo } : {}), }, - consumer: 'bar', + consumer: consumer ?? 'bar', relatedSavedObjects: [ { id: '1', @@ -444,6 +450,8 @@ export const generateEnqueueFunctionInput = ({ type: 'SAVED_OBJECT', }, spaceId: 'default', + ...(priority && { priority }), + ...(apiKeyId && { apiKeyId }), }; return isBulk ? [input] : input; }; diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/task_runner_alerts_client.test.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/task_runner_alerts_client.test.ts index 3d0cd5ab05059..2c8c7daf7f13a 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/task_runner_alerts_client.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/task_runner_alerts_client.test.ts @@ -593,7 +593,7 @@ describe('Task Runner', () => { index: '.alerts-test.alerts-default', refresh: 'wait_for', require_alias: !useDataStreamForAlerts, - body: [ + operations: [ { create: { _id: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/transform_action_params.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/transform_action_params.ts index cb28d0aefcbd0..0b23910be3f3d 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/transform_action_params.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/transform_action_params.ts @@ -14,8 +14,8 @@ import { AlertInstanceState, AlertInstanceContext, RuleTypeParams, - SanitizedRule, } from '../types'; +import { ActionSchedulerRule } from './action_scheduler/types'; export interface TransformActionParamsOptions { actionsPlugin: ActionsPluginStartContract; @@ -146,7 +146,7 @@ export function transformSummaryActionParams({ kibanaBaseUrl, }: { alerts: SummarizedAlertsWithAll; - rule: SanitizedRule; + rule: ActionSchedulerRule; ruleTypeId: string; actionsPlugin: ActionsPluginStartContract; actionId: string; diff --git a/x-pack/platform/plugins/shared/alerting/server/usage/lib/get_telemetry_from_alerts.ts b/x-pack/platform/plugins/shared/alerting/server/usage/lib/get_telemetry_from_alerts.ts index f5537687fd3dd..ae92255bd2cd4 100644 --- a/x-pack/platform/plugins/shared/alerting/server/usage/lib/get_telemetry_from_alerts.ts +++ b/x-pack/platform/plugins/shared/alerting/server/usage/lib/get_telemetry_from_alerts.ts @@ -8,7 +8,7 @@ import type { AggregationsTermsAggregateBase, AggregationsStringTermsBucketKeys, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient, Logger } from '@kbn/core/server'; import { NUM_ALERTING_RULE_TYPES } from '../alerting_usage_collector'; @@ -38,16 +38,14 @@ export async function getTotalAlertsCountAggregations({ const query = { index: AAD_INDEX_PATTERN, size: 0, - body: { - query: { - match_all: {}, - }, - aggs: { - by_rule_type_id: { - terms: { - field: 'kibana.alert.rule.rule_type_id', - size: NUM_ALERTING_RULE_TYPES, - }, + query: { + match_all: {}, + }, + aggs: { + by_rule_type_id: { + terms: { + field: 'kibana.alert.rule.rule_type_id', + size: NUM_ALERTING_RULE_TYPES, }, }, }, diff --git a/x-pack/platform/plugins/shared/alerting/server/usage/lib/get_telemetry_from_event_log.ts b/x-pack/platform/plugins/shared/alerting/server/usage/lib/get_telemetry_from_event_log.ts index df76929ca5d50..b25b1e59f03af 100644 --- a/x-pack/platform/plugins/shared/alerting/server/usage/lib/get_telemetry_from_event_log.ts +++ b/x-pack/platform/plugins/shared/alerting/server/usage/lib/get_telemetry_from_event_log.ts @@ -14,7 +14,7 @@ import type { AggregationsTermsAggregateBase, AggregationsStringTermsBucketKeys, AggregationsBuckets, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient, Logger } from '@kbn/core/server'; import { NUM_ALERTING_RULE_TYPES, @@ -136,21 +136,19 @@ export async function getExecutionsPerDayCount({ const query = { index: eventLogIndex, size: 0, - body: { - query: getProviderAndActionFilterForTimeRange('execute'), - aggs: { - ...eventLogAggs, - by_rule_type_id: { - terms: { - field: 'rule.category', - size: NUM_ALERTING_RULE_TYPES, - }, - aggs: eventLogAggs, + query: getProviderAndActionFilterForTimeRange('execute'), + aggs: { + ...eventLogAggs, + by_rule_type_id: { + terms: { + field: 'rule.category', + size: NUM_ALERTING_RULE_TYPES, }, - by_execution_status: { - terms: { - field: 'event.outcome', - }, + aggs: eventLogAggs, + }, + by_execution_status: { + terms: { + field: 'event.outcome', }, }, }, @@ -229,14 +227,12 @@ export async function getExecutionTimeoutsPerDayCount({ const query = { index: eventLogIndex, size: 0, - body: { - query: getProviderAndActionFilterForTimeRange('execute-timeout'), - aggs: { - by_rule_type_id: { - terms: { - field: 'rule.category', - size: NUM_ALERTING_RULE_TYPES, - }, + query: getProviderAndActionFilterForTimeRange('execute-timeout'), + aggs: { + by_rule_type_id: { + terms: { + field: 'rule.category', + size: NUM_ALERTING_RULE_TYPES, }, }, }, diff --git a/x-pack/platform/plugins/shared/alerting/server/usage/lib/get_telemetry_from_kibana.ts b/x-pack/platform/plugins/shared/alerting/server/usage/lib/get_telemetry_from_kibana.ts index 756512815d901..509035c5808b1 100644 --- a/x-pack/platform/plugins/shared/alerting/server/usage/lib/get_telemetry_from_kibana.ts +++ b/x-pack/platform/plugins/shared/alerting/server/usage/lib/get_telemetry_from_kibana.ts @@ -10,7 +10,7 @@ import type { AggregationsCardinalityAggregate, AggregationsTermsAggregateBase, AggregationsStringTermsBucketKeys, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient, Logger, ISavedObjectsRepository } from '@kbn/core/server'; import { @@ -83,18 +83,17 @@ export async function getTotalCountAggregations({ const query = { index: alertIndex, size: 0, - body: { - query: { - bool: { - // Aggregate over all rule saved objects - filter: [{ term: { type: 'alert' } }], - }, + query: { + bool: { + // Aggregate over all rule saved objects + filter: [{ term: { type: 'alert' } }], }, - runtime_mappings: { - rule_action_count: { - type: 'long', - script: { - source: ` + }, + runtime_mappings: { + rule_action_count: { + type: 'long', + script: { + source: ` def alert = params._source['alert']; if (alert != null) { def actions = alert.actions; @@ -104,13 +103,13 @@ export async function getTotalCountAggregations({ emit(0); } }`, - }, }, - // Convert schedule interval duration string from rule saved object to interval in seconds - rule_schedule_interval: { - type: 'long', - script: { - source: ` + }, + // Convert schedule interval duration string from rule saved object to interval in seconds + rule_schedule_interval: { + type: 'long', + script: { + source: ` int parsed = 0; if (doc['alert.schedule.interval'].size() > 0) { def interval = doc['alert.schedule.interval'].value; @@ -140,13 +139,13 @@ export async function getTotalCountAggregations({ } emit(parsed); `, - }, }, - // Convert throttle interval duration string from rule saved object to interval in seconds - rule_throttle_interval: { - type: 'long', - script: { - source: ` + }, + // Convert throttle interval duration string from rule saved object to interval in seconds + rule_throttle_interval: { + type: 'long', + script: { + source: ` int parsed = 0; if (doc['alert.throttle'].size() > 0) { def throttle = doc['alert.throttle'].value; @@ -176,12 +175,12 @@ export async function getTotalCountAggregations({ } emit(parsed); `, - }, }, - rule_with_tags: { - type: 'long', - script: { - source: ` + }, + rule_with_tags: { + type: 'long', + script: { + source: ` def rule = params._source['alert']; if (rule != null && rule.tags != null) { if (rule.tags.size() > 0) { @@ -190,12 +189,12 @@ export async function getTotalCountAggregations({ emit(0); } }`, - }, }, - rule_snoozed: { - type: 'long', - script: { - source: ` + }, + rule_snoozed: { + type: 'long', + script: { + source: ` def rule = params._source['alert']; if (rule != null && rule.snoozeSchedule != null) { if (rule.snoozeSchedule.size() > 0) { @@ -204,23 +203,23 @@ export async function getTotalCountAggregations({ emit(0); } }`, - }, }, - rule_muted: { - type: 'long', - script: { - source: ` + }, + rule_muted: { + type: 'long', + script: { + source: ` if (doc['alert.muteAll'].value == true) { emit(1); } else { emit(0); }`, - }, }, - rule_with_muted_alerts: { - type: 'long', - script: { - source: ` + }, + rule_with_muted_alerts: { + type: 'long', + script: { + source: ` def rule = params._source['alert']; if (rule != null && rule.mutedInstanceIds != null) { if (rule.mutedInstanceIds.size() > 0) { @@ -229,64 +228,63 @@ export async function getTotalCountAggregations({ emit(0); } }`, - }, }, }, - aggs: { - by_rule_type_id: { - terms: { - field: 'alert.alertTypeId', - size: NUM_ALERTING_RULE_TYPES, - }, + }, + aggs: { + by_rule_type_id: { + terms: { + field: 'alert.alertTypeId', + size: NUM_ALERTING_RULE_TYPES, }, - max_throttle_time: { max: { field: 'rule_throttle_interval' } }, - min_throttle_time: { min: { field: 'rule_throttle_interval' } }, - avg_throttle_time: { avg: { field: 'rule_throttle_interval' } }, - max_interval_time: { max: { field: 'rule_schedule_interval' } }, - min_interval_time: { min: { field: 'rule_schedule_interval' } }, - avg_interval_time: { avg: { field: 'rule_schedule_interval' } }, - max_actions_count: { max: { field: 'rule_action_count' } }, - min_actions_count: { min: { field: 'rule_action_count' } }, - avg_actions_count: { avg: { field: 'rule_action_count' } }, - by_execution_status: { - terms: { - field: 'alert.executionStatus.status', - }, + }, + max_throttle_time: { max: { field: 'rule_throttle_interval' } }, + min_throttle_time: { min: { field: 'rule_throttle_interval' } }, + avg_throttle_time: { avg: { field: 'rule_throttle_interval' } }, + max_interval_time: { max: { field: 'rule_schedule_interval' } }, + min_interval_time: { min: { field: 'rule_schedule_interval' } }, + avg_interval_time: { avg: { field: 'rule_schedule_interval' } }, + max_actions_count: { max: { field: 'rule_action_count' } }, + min_actions_count: { min: { field: 'rule_action_count' } }, + avg_actions_count: { avg: { field: 'rule_action_count' } }, + by_execution_status: { + terms: { + field: 'alert.executionStatus.status', }, - by_notify_when: { - terms: { - field: 'alert.notifyWhen', - }, + }, + by_notify_when: { + terms: { + field: 'alert.notifyWhen', }, - connector_types_by_consumers: { - terms: { - field: 'alert.consumer', - }, - aggs: { - actions: { - nested: { - path: 'alert.actions', - }, - aggs: { - connector_types: { - terms: { - field: 'alert.actions.actionTypeId', - }, + }, + connector_types_by_consumers: { + terms: { + field: 'alert.consumer', + }, + aggs: { + actions: { + nested: { + path: 'alert.actions', + }, + aggs: { + connector_types: { + terms: { + field: 'alert.actions.actionTypeId', }, }, }, }, }, - by_search_type: { - terms: { - field: 'alert.params.searchType', - }, + }, + by_search_type: { + terms: { + field: 'alert.params.searchType', }, - sum_rules_with_tags: { sum: { field: 'rule_with_tags' } }, - sum_rules_snoozed: { sum: { field: 'rule_snoozed' } }, - sum_rules_muted: { sum: { field: 'rule_muted' } }, - sum_rules_with_muted_alerts: { sum: { field: 'rule_with_muted_alerts' } }, }, + sum_rules_with_tags: { sum: { field: 'rule_with_tags' } }, + sum_rules_snoozed: { sum: { field: 'rule_snoozed' } }, + sum_rules_muted: { sum: { field: 'rule_muted' } }, + sum_rules_with_muted_alerts: { sum: { field: 'rule_with_muted_alerts' } }, }, }; @@ -439,25 +437,23 @@ export async function getTotalCountInUse({ const query = { index: alertIndex, size: 0, - body: { - query: { - bool: { - // Aggregate over only enabled rule saved objects - filter: [{ term: { type: 'alert' } }, { term: { 'alert.enabled': true } }], - }, + query: { + bool: { + // Aggregate over only enabled rule saved objects + filter: [{ term: { type: 'alert' } }, { term: { 'alert.enabled': true } }], }, - aggs: { - namespaces_count: { cardinality: { field: 'namespaces' } }, - by_rule_type_id: { - terms: { - field: 'alert.alertTypeId', - size: NUM_ALERTING_RULE_TYPES, - }, + }, + aggs: { + namespaces_count: { cardinality: { field: 'namespaces' } }, + by_rule_type_id: { + terms: { + field: 'alert.alertTypeId', + size: NUM_ALERTING_RULE_TYPES, }, - by_search_type: { - terms: { - field: 'alert.params.searchType', - }, + }, + by_search_type: { + terms: { + field: 'alert.params.searchType', }, }, }, diff --git a/x-pack/platform/plugins/shared/alerting/server/usage/lib/get_telemetry_from_task_manager.ts b/x-pack/platform/plugins/shared/alerting/server/usage/lib/get_telemetry_from_task_manager.ts index f3741a086bf9b..973e5d755dcd9 100644 --- a/x-pack/platform/plugins/shared/alerting/server/usage/lib/get_telemetry_from_task_manager.ts +++ b/x-pack/platform/plugins/shared/alerting/server/usage/lib/get_telemetry_from_task_manager.ts @@ -10,7 +10,7 @@ import type { AggregationsTermsAggregateBase, AggregationsStringTermsBucketKeys, AggregationsBuckets, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient, Logger } from '@kbn/core/server'; import { replaceDotSymbols } from './replace_dots_with_underscores'; import { NUM_ALERTING_RULE_TYPES } from '../alerting_usage_collector'; @@ -42,58 +42,56 @@ export async function getFailedAndUnrecognizedTasksPerDay({ const query = { index: taskManagerIndex, size: 0, - body: { - query: { - bool: { - must: [ - { - bool: { - should: [ - { - term: { - 'task.status': 'unrecognized', - }, + query: { + bool: { + must: [ + { + bool: { + should: [ + { + term: { + 'task.status': 'unrecognized', }, - { - term: { - 'task.status': 'failed', - }, + }, + { + term: { + 'task.status': 'failed', }, - ], - }, - }, - { - wildcard: { - 'task.taskType': { - value: 'alerting:*', }, - }, + ], }, - { - range: { - 'task.runAt': { - gte: 'now-1d', - }, + }, + { + wildcard: { + 'task.taskType': { + value: 'alerting:*', }, }, - ], - }, - }, - aggs: { - by_status: { - terms: { - field: 'task.status', - size: 10, }, - aggs: { - by_task_type: { - terms: { - field: 'task.taskType', - // Use number of alerting rule types because we're filtering by 'alerting:' - size: NUM_ALERTING_RULE_TYPES, + { + range: { + 'task.runAt': { + gte: 'now-1d', }, }, }, + ], + }, + }, + aggs: { + by_status: { + terms: { + field: 'task.status', + size: 10, + }, + aggs: { + by_task_type: { + terms: { + field: 'task.taskType', + // Use number of alerting rule types because we're filtering by 'alerting:' + size: NUM_ALERTING_RULE_TYPES, + }, + }, }, }, }, diff --git a/x-pack/platform/plugins/shared/alerting/server/usage/lib/group_connectors_by_consumers.ts b/x-pack/platform/plugins/shared/alerting/server/usage/lib/group_connectors_by_consumers.ts index 3c29f31f0eb9f..21c7a9b4737d4 100644 --- a/x-pack/platform/plugins/shared/alerting/server/usage/lib/group_connectors_by_consumers.ts +++ b/x-pack/platform/plugins/shared/alerting/server/usage/lib/group_connectors_by_consumers.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { AggregationsBuckets } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { AggregationsBuckets } from '@elastic/elasticsearch/lib/api/types'; import { replaceDotSymbols } from './replace_dots_with_underscores'; export interface ConnectorsByConsumersBucket { diff --git a/x-pack/platform/plugins/shared/alerting/server/usage/lib/parse_simple_rule_type_bucket.ts b/x-pack/platform/plugins/shared/alerting/server/usage/lib/parse_simple_rule_type_bucket.ts index f3d3007061365..8af7fc6d5e15b 100644 --- a/x-pack/platform/plugins/shared/alerting/server/usage/lib/parse_simple_rule_type_bucket.ts +++ b/x-pack/platform/plugins/shared/alerting/server/usage/lib/parse_simple_rule_type_bucket.ts @@ -8,7 +8,7 @@ import { AggregationsBuckets, AggregationsStringTermsBucketKeys, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import { replaceDotSymbols } from './replace_dots_with_underscores'; export function parseSimpleRuleTypeBucket( diff --git a/x-pack/platform/plugins/shared/cases/common/api/helpers.ts b/x-pack/platform/plugins/shared/cases/common/api/helpers.ts index fcdf2be6b6159..45dad60a9bad1 100644 --- a/x-pack/platform/plugins/shared/cases/common/api/helpers.ts +++ b/x-pack/platform/plugins/shared/cases/common/api/helpers.ts @@ -14,7 +14,7 @@ import { CASE_CONFIGURE_DETAILS_URL, CASE_ALERTS_URL, CASE_COMMENT_DELETE_URL, - CASE_FIND_USER_ACTIONS_URL, + INTERNAL_CASE_FIND_USER_ACTIONS_URL, INTERNAL_GET_CASE_USER_ACTIONS_STATS_URL, INTERNAL_BULK_GET_ATTACHMENTS_URL, INTERNAL_CONNECTORS_URL, @@ -57,7 +57,7 @@ export const getCaseUserActionStatsUrl = (id: string): string => { }; export const getCaseFindUserActionsUrl = (id: string): string => { - return CASE_FIND_USER_ACTIONS_URL.replace('{case_id}', id); + return INTERNAL_CASE_FIND_USER_ACTIONS_URL.replace('{case_id}', id); }; export const getCasePushUrl = (caseId: string, connectorId: string): string => { diff --git a/x-pack/platform/plugins/shared/cases/common/constants/index.ts b/x-pack/platform/plugins/shared/cases/common/constants/index.ts index 70a7f73bd4526..76787c791b808 100644 --- a/x-pack/platform/plugins/shared/cases/common/constants/index.ts +++ b/x-pack/platform/plugins/shared/cases/common/constants/index.ts @@ -92,6 +92,8 @@ export const INTERNAL_CASE_OBSERVABLES_PATCH_URL = `${INTERNAL_CASE_OBSERVABLES_URL}/{observable_id}` as const; export const INTERNAL_CASE_OBSERVABLES_DELETE_URL = `${INTERNAL_CASE_OBSERVABLES_URL}/{observable_id}` as const; +export const INTERNAL_CASE_FIND_USER_ACTIONS_URL = + `${CASES_INTERNAL_URL}/{case_id}/user_actions/_find` as const; /** * Action routes diff --git a/x-pack/platform/plugins/shared/cases/common/types/api/user_action/v1.ts b/x-pack/platform/plugins/shared/cases/common/types/api/user_action/v1.ts index 444a8bfe8e4e2..2ca14454e72d6 100644 --- a/x-pack/platform/plugins/shared/cases/common/types/api/user_action/v1.ts +++ b/x-pack/platform/plugins/shared/cases/common/types/api/user_action/v1.ts @@ -15,6 +15,7 @@ import { CaseUserActionBasicRt, UserActionsRt, } from '../../domain/user_action/v1'; +import type { Attachments } from '../../domain'; export type UserActionWithResponse = T & { id: string; version: string } & rt.TypeOf< typeof CaseUserActionInjectedIdsRt @@ -85,3 +86,7 @@ export const UserActionFindResponseRt = rt.strict({ }); export type UserActionFindResponse = rt.TypeOf; + +export interface UserActionInternalFindResponse extends UserActionFindResponse { + latestAttachments: Attachments; +} diff --git a/x-pack/platform/plugins/shared/cases/common/types/domain/attachment/v1.ts b/x-pack/platform/plugins/shared/cases/common/types/domain/attachment/v1.ts index 1dbf1129f58c5..e1e01052d4a89 100644 --- a/x-pack/platform/plugins/shared/cases/common/types/domain/attachment/v1.ts +++ b/x-pack/platform/plugins/shared/cases/common/types/domain/attachment/v1.ts @@ -295,6 +295,15 @@ export type PersistableStateAttachmentAttributes = rt.TypeOf< * Common */ +export const AttachmentPayloadRt = rt.union([ + UserCommentAttachmentPayloadRt, + AlertAttachmentPayloadRt, + ActionsAttachmentPayloadRt, + ExternalReferenceNoSOAttachmentPayloadRt, + ExternalReferenceSOAttachmentPayloadRt, + PersistableStateAttachmentPayloadRt, +]); + export const AttachmentAttributesRt = rt.union([ UserCommentAttachmentAttributesRt, AlertAttachmentAttributesRt, diff --git a/x-pack/platform/plugins/shared/cases/common/types/domain/case/v1.ts b/x-pack/platform/plugins/shared/cases/common/types/domain/case/v1.ts index 14051228452ed..afda0cd14291e 100644 --- a/x-pack/platform/plugins/shared/cases/common/types/domain/case/v1.ts +++ b/x-pack/platform/plugins/shared/cases/common/types/domain/case/v1.ts @@ -162,6 +162,7 @@ export const RelatedCaseRt = rt.strict({ export const SimilarityRt = rt.strict({ typeKey: rt.string, + typeLabel: rt.string, value: rt.string, }); diff --git a/x-pack/platform/plugins/shared/cases/common/types/domain/user_action/comment/v1.ts b/x-pack/platform/plugins/shared/cases/common/types/domain/user_action/comment/v1.ts index a29f95b40d4d6..f86ff42e87b53 100644 --- a/x-pack/platform/plugins/shared/cases/common/types/domain/user_action/comment/v1.ts +++ b/x-pack/platform/plugins/shared/cases/common/types/domain/user_action/comment/v1.ts @@ -6,10 +6,12 @@ */ import * as rt from 'io-ts'; -import { AttachmentRequestRt, AttachmentRequestWithoutRefsRt } from '../../../api/attachment/v1'; +import { AttachmentRequestWithoutRefsRt } from '../../../api/attachment/v1'; import { UserActionTypes } from '../action/v1'; +import { AttachmentPayloadRt } from '../../attachment/v1'; + +export const CommentUserActionPayloadRt = rt.strict({ comment: AttachmentPayloadRt }); -export const CommentUserActionPayloadRt = rt.strict({ comment: AttachmentRequestRt }); export const CommentUserActionPayloadWithoutIdsRt = rt.strict({ comment: AttachmentRequestWithoutRefsRt, }); diff --git a/x-pack/platform/plugins/shared/cases/common/ui/types.ts b/x-pack/platform/plugins/shared/cases/common/ui/types.ts index 72b102d34770d..827caecadce21 100644 --- a/x-pack/platform/plugins/shared/cases/common/ui/types.ts +++ b/x-pack/platform/plugins/shared/cases/common/ui/types.ts @@ -97,6 +97,11 @@ export type UserActionUI = SnakeToCamelCase; export type FindCaseUserActions = Omit, 'userActions'> & { userActions: UserActionUI[]; }; + +export interface InternalFindCaseUserActions extends FindCaseUserActions { + latestAttachments: AttachmentUI[]; +} + export type CaseUserActionsStats = SnakeToCamelCase; export type CaseUI = Omit, 'comments'> & { comments: AttachmentUI[]; diff --git a/x-pack/platform/plugins/shared/cases/public/components/case_view/components/case_view_activity.test.tsx b/x-pack/platform/plugins/shared/cases/public/components/case_view/components/case_view_activity.test.tsx index fafc67fd1a5a2..1981ddc671c65 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/case_view/components/case_view_activity.test.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/case_view/components/case_view_activity.test.tsx @@ -38,7 +38,7 @@ import { useGetCaseUserActionsStats } from '../../../containers/use_get_case_use import { useInfiniteFindCaseUserActions } from '../../../containers/use_infinite_find_case_user_actions'; import { useOnUpdateField } from '../use_on_update_field'; import { useCasesFeatures } from '../../../common/use_cases_features'; -import { ConnectorTypes, UserActionTypes } from '../../../../common/types/domain'; +import { AttachmentType, ConnectorTypes, UserActionTypes } from '../../../../common/types/domain'; import { CaseMetricsFeature } from '../../../../common/types/api'; import { useGetCaseConfiguration } from '../../../containers/configure/use_get_case_configuration'; import { useGetCurrentUserProfile } from '../../../containers/user_profiles/use_get_current_user_profile'; @@ -147,6 +147,8 @@ const useOnUpdateFieldMock = useOnUpdateField as jest.Mock; const useCasesFeaturesMock = useCasesFeatures as jest.Mock; const useReplaceCustomFieldMock = useReplaceCustomField as jest.Mock; +const localStorageKey = `${basicCase.owner}.cases.userActivity.sortOrder`; + describe('Case View Page activity tab', () => { let appMockRender: AppMockRenderer; const caseConnectors = getCaseConnectorsMockResponse(); @@ -217,6 +219,8 @@ describe('Case View Page activity tab', () => { jest.clearAllMocks(); appMockRender = createAppMockRenderer(); + localStorage.clear(); + useGetCaseUsersMock.mockReturnValue({ isLoading: false, data: caseUsers }); useCasesFeaturesMock.mockReturnValue(useGetCasesFeaturesRes); }); @@ -391,6 +395,29 @@ describe('Case View Page activity tab', () => { expect(await screen.findByTestId('case-view-edit-connector')).toBeInTheDocument(); }); + it('should save sortOrder in localstorage', async () => { + (useGetCaseConfiguration as jest.Mock).mockReturnValue({ + data: { + customFields: [customFieldsConfigurationMock[1]], + observableTypes: [], + }, + }); + + appMockRender.render( + + ); + + await userEvent.selectOptions(await screen.findByTestId('user-actions-sort-select'), 'desc'); + + expect(localStorage.getItem(localStorageKey)).toBe('"desc"'); + }); + describe('filter activity', () => { beforeEach(() => { jest.clearAllMocks(); @@ -543,6 +570,14 @@ describe('Case View Page activity tab', () => { }); it('renders the user action users correctly', async () => { + const commentUpdate = getUserAction('comment', 'update', { + createdBy: { + ...caseUsers.participants[1].user, + fullName: caseUsers.participants[1].user.full_name, + profileUid: caseUsers.participants[1].uid, + }, + }); + useFindCaseUserActionsMock.mockReturnValue({ ...defaultUseFindCaseUserActions, data: { @@ -555,13 +590,7 @@ describe('Case View Page activity tab', () => { profileUid: caseUsers.participants[0].uid, }, }), - getUserAction('comment', 'update', { - createdBy: { - ...caseUsers.participants[1].user, - fullName: caseUsers.participants[1].user.full_name, - profileUid: caseUsers.participants[1].uid, - }, - }), + commentUpdate, getUserAction('description', 'update', { createdBy: { ...caseUsers.participants[2].user, @@ -584,6 +613,25 @@ describe('Case View Page activity tab', () => { }, }), ], + latestAttachments: + commentUpdate.type === 'comment' && + commentUpdate.payload.comment?.type === AttachmentType.user + ? [ + { + comment: commentUpdate.payload.comment.comment, + createdAt: commentUpdate.createdAt, + createdBy: commentUpdate.createdBy, + id: commentUpdate.commentId, + owner: commentUpdate.owner, + pushed_at: null, + pushed_by: null, + type: 'user', + updated_at: null, + updated_by: null, + version: commentUpdate.version, + }, + ] + : [], }, }); diff --git a/x-pack/platform/plugins/shared/cases/public/components/case_view/components/case_view_activity.tsx b/x-pack/platform/plugins/shared/cases/public/components/case_view/components/case_view_activity.tsx index 6e945ef836272..e92edc0899bc3 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/case_view/components/case_view_activity.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/case_view/components/case_view_activity.tsx @@ -16,6 +16,7 @@ import { } from '@elastic/eui'; import React, { useCallback, useMemo, useState } from 'react'; import { isEqual } from 'lodash'; +import { useCasesLocalStorage } from '../../../common/use_cases_local_storage'; import { useGetCaseConfiguration } from '../../../containers/configure/use_get_case_configuration'; import { useGetCaseUsers } from '../../../containers/use_get_case_users'; import { useGetCaseConnectors } from '../../../containers/use_get_case_connectors'; @@ -40,7 +41,10 @@ import { useGetCaseUserActionsStats } from '../../../containers/use_get_case_use import { AssignUsers } from './assign_users'; import { UserActionsActivityBar } from '../../user_actions_activity_bar'; import type { Assignee } from '../../user_profiles/types'; -import type { UserActivityParams } from '../../user_actions_activity_bar/types'; +import type { + UserActivityParams, + UserActivitySortOrder, +} from '../../user_actions_activity_bar/types'; import { CASE_VIEW_PAGE_TABS } from '../../../../common/types'; import { CaseViewTabs } from '../case_view_tabs'; import { Description } from '../../description'; @@ -49,6 +53,8 @@ import { parseCaseUsers } from '../../utils'; import { CustomFields } from './custom_fields'; import { useReplaceCustomField } from '../../../containers/use_replace_custom_field'; +const LOCALSTORAGE_SORT_ORDER_KEY = 'cases.userActivity.sortOrder'; + export const CaseViewActivity = ({ ruleDetailsNavigation, caseData, @@ -62,9 +68,14 @@ export const CaseViewActivity = ({ showAlertDetails?: (alertId: string, index: string) => void; useFetchAlertData: UseFetchAlertData; }) => { + const [sortOrder, setSortOrder] = useCasesLocalStorage( + LOCALSTORAGE_SORT_ORDER_KEY, + 'asc' + ); + const [userActivityQueryParams, setUserActivityQueryParams] = useState({ type: 'all', - sortOrder: 'asc', + sortOrder, page: 1, perPage: 10, }); @@ -167,6 +178,7 @@ export const CaseViewActivity = ({ const handleUserActionsActivityChanged = useCallback( (params: UserActivityParams) => { + setSortOrder(params.sortOrder); setUserActivityQueryParams((oldParams) => ({ ...oldParams, page: 1, @@ -174,7 +186,7 @@ export const CaseViewActivity = ({ sortOrder: params.sortOrder, })); }, - [setUserActivityQueryParams] + [setSortOrder, setUserActivityQueryParams] ); const showUserActions = diff --git a/x-pack/platform/plugins/shared/cases/public/components/case_view/components/case_view_similar_cases.tsx b/x-pack/platform/plugins/shared/cases/public/components/case_view/components/case_view_similar_cases.tsx index cb72af1fa0e1f..562653415d73d 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/case_view/components/case_view_similar_cases.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/case_view/components/case_view_similar_cases.tsx @@ -24,7 +24,7 @@ export const CaseViewSimilarCases = ({ caseData }: CaseViewSimilarCasesProps) => const [pageIndex, setPageIndex] = useState(0); const [pageSize, setPageSize] = useState(CASES_TABLE_PER_PAGE_VALUES[0]); - const { data = initialData, isFetching: isLoadingCases } = useGetSimilarCases({ + const { data = initialData, isLoading: isLoadingCases } = useGetSimilarCases({ caseId: caseData.id, page: pageIndex + 1, perPage: pageSize, diff --git a/x-pack/platform/plugins/shared/cases/public/components/case_view/mocks.ts b/x-pack/platform/plugins/shared/cases/public/components/case_view/mocks.ts index f6764ae133401..40309d099fb2c 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/case_view/mocks.ts +++ b/x-pack/platform/plugins/shared/cases/public/components/case_view/mocks.ts @@ -13,7 +13,7 @@ import { caseUserActions, getAlertUserAction, } from '../../containers/mock'; -import type { CaseUI } from '../../containers/types'; +import type { CaseUI, UserActionUI } from '../../containers/types'; import type { CaseViewProps } from './types'; export const alertsHit = [ @@ -99,8 +99,51 @@ export const defaultUpdateCaseState = { mutate: jest.fn(), }; +const generateLatestAttachments = ({ + userActions, + overrides, +}: { + userActions: UserActionUI[]; + overrides: Array<{ commentId: string; comment: string }>; +}) => { + return userActions + .filter( + ( + userAction + ): userAction is UserActionUI & { + type: 'comment'; + payload: { comment: { comment: string } }; + } => userAction.type === 'comment' && Boolean(userAction.commentId) + ) + .map((userAction) => { + const override = overrides.find(({ commentId }) => commentId === userAction.commentId); + return { + comment: override ? override.comment : userAction.payload.comment?.comment, + createdAt: userAction.createdAt, + createdBy: userAction.createdBy, + id: userAction.commentId, + owner: userAction.owner, + pushed_at: null, + pushed_by: null, + type: 'user', + updated_at: null, + updated_by: null, + version: userAction.version, + }; + }); +}; + export const defaultUseFindCaseUserActions = { - data: { total: 4, perPage: 10, page: 1, userActions: [...caseUserActions, getAlertUserAction()] }, + data: { + total: 4, + perPage: 10, + page: 1, + userActions: [...caseUserActions, getAlertUserAction()], + latestAttachments: generateLatestAttachments({ + userActions: [...caseUserActions, getAlertUserAction()], + overrides: [{ commentId: 'basic-comment-id', comment: 'Solve this fast!' }], + }), + }, refetch: jest.fn(), isLoading: false, isFetching: false, @@ -110,7 +153,13 @@ export const defaultUseFindCaseUserActions = { export const defaultInfiniteUseFindCaseUserActions = { data: { pages: [ - { total: 4, perPage: 10, page: 1, userActions: [...caseUserActions, getAlertUserAction()] }, + { + total: 4, + perPage: 10, + page: 1, + userActions: [...caseUserActions, getAlertUserAction()], + latestAttachments: [], + }, ], }, isLoading: false, diff --git a/x-pack/platform/plugins/shared/cases/public/components/files/file_name_link.test.tsx b/x-pack/platform/plugins/shared/cases/public/components/files/file_name_link.test.tsx index 82944c772b170..c7536df5683e6 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/files/file_name_link.test.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/files/file_name_link.test.tsx @@ -12,7 +12,8 @@ import userEvent from '@testing-library/user-event'; import { basicFileMock } from '../../containers/mock'; import { FileNameLink } from './file_name_link'; -describe('FileNameLink', () => { +// Failing: See https://github.com/elastic/kibana/issues/207369 +describe.skip('FileNameLink', () => { const defaultProps = { file: basicFileMock, showPreview: jest.fn(), diff --git a/x-pack/platform/plugins/shared/cases/public/components/similar_cases/table.test.tsx b/x-pack/platform/plugins/shared/cases/public/components/similar_cases/table.test.tsx index 2d3de8b54ae93..99a406d482954 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/similar_cases/table.test.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/similar_cases/table.test.tsx @@ -8,12 +8,12 @@ import React from 'react'; import { type AppMockRenderer, createAppMockRenderer } from '../../common/mock'; import { SimilarCasesTable, type SimilarCasesTableProps } from './table'; -import { mockCase, mockObservables } from '../../containers/mock'; +import { mockCase, mockSimilarObservables } from '../../containers/mock'; describe('SimilarCasesTable', () => { let appMock: AppMockRenderer; const props: SimilarCasesTableProps = { - cases: [{ ...mockCase, similarities: { observables: mockObservables } }], + cases: [{ ...mockCase, similarities: { observables: mockSimilarObservables } }], isLoading: false, onChange: jest.fn(), pagination: { pageIndex: 0, totalItemCount: 1 }, @@ -30,6 +30,12 @@ describe('SimilarCasesTable', () => { expect(result.getByTestId('similar-cases-table')).toBeInTheDocument(); }); + it('renders similarities correctly', async () => { + const result = appMock.render(); + + expect(await result.findByTestId('similar-cases-table-column-similarities')).toBeTruthy(); + }); + it('renders loading indicator when loading', async () => { const result = appMock.render(); expect(result.queryByTestId('similar-cases-table')).not.toBeInTheDocument(); diff --git a/x-pack/platform/plugins/shared/cases/public/components/similar_cases/use_similar_cases_columns.tsx b/x-pack/platform/plugins/shared/cases/public/components/similar_cases/use_similar_cases_columns.tsx index fe6075ca06cb9..20c4b6f61d719 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/similar_cases/use_similar_cases_columns.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/similar_cases/use_similar_cases_columns.tsx @@ -47,13 +47,14 @@ export interface UseSimilarCasesColumnsReturnValue { export const useSimilarCasesColumns = (): UseSimilarCasesColumnsReturnValue => { const casesColumnsConfig = useCasesColumnsConfiguration(false); + const columns: SimilarCasesColumns[] = useMemo( () => [ { field: casesColumnsConfig.title.field, name: casesColumnsConfig.title.name, sortable: false, - render: (title: string, theCase: SimilarCaseUI) => { + render: (_title: string, theCase: SimilarCaseUI) => { if (theCase.id != null && theCase.title != null) { const caseDetailsLinkComponent = ( @@ -171,16 +172,74 @@ export const useSimilarCasesColumns = (): UseSimilarCasesColumnsReturnValue => { field: SIMILARITIES_FIELD, name: i18n.SIMILARITY_REASON, sortable: false, - render: (similarities: SimilarCaseUI['similarities'], theCase: SimilarCaseUI) => { - if (theCase.id != null && theCase.title != null) { - return similarities.observables.map((similarity) => similarity.value).join(', '); + render: (similarities: SimilarCaseUI['similarities']) => { + const similarObservableValues = similarities.observables.map( + (similarity) => `${similarity.typeLabel}:${similarity.value}` + ); + + if (similarObservableValues.length > 0) { + const clampedBadges = ( + + {similarObservableValues.map((similarValue: string) => ( + + {similarValue} + + ))} + + ); + + const unclampedBadges = ( + + {similarObservableValues.map((similarValue: string) => ( + + {similarValue} + + ))} + + ); + + return ( + + {clampedBadges} + + ); } return getEmptyCellValue(); }, width: '20%', }, ], - [casesColumnsConfig] + [ + casesColumnsConfig.category.field, + casesColumnsConfig.category.name, + casesColumnsConfig.severity.field, + casesColumnsConfig.severity.name, + casesColumnsConfig.status.field, + casesColumnsConfig.status.name, + casesColumnsConfig.tags.field, + casesColumnsConfig.tags.name, + casesColumnsConfig.title.field, + casesColumnsConfig.title.name, + ] ); return { columns, rowHeader: casesColumnsConfig.title.field }; diff --git a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/actions.tsx b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/actions.tsx index 84f0ed768edf6..46acf1d8a2cee 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/actions.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/actions.tsx @@ -21,29 +21,32 @@ type BuilderArgs = Pick< UserActionBuilderArgs, 'userAction' | 'actionsNavigation' | 'userProfiles' > & { - comment: SnakeToCamelCase; + attachment: SnakeToCamelCase; }; export const createActionAttachmentUserActionBuilder = ({ userAction, userProfiles, - comment, + attachment, actionsNavigation, }: BuilderArgs): ReturnType => ({ build: () => { - const actionIconName = comment.actions.type === 'isolate' ? 'lock' : 'lockOpen'; + const actionIconName = attachment.actions.type === 'isolate' ? 'lock' : 'lockOpen'; return [ { username: ( - + ), className: classNames('comment-action', { - 'empty-comment': comment.comment.trim().length === 0, + 'empty-comment': attachment.comment.trim().length === 0, }), event: ( @@ -52,9 +55,9 @@ export const createActionAttachmentUserActionBuilder = ({ timestamp: , timelineAvatar: actionIconName, timelineAvatarAriaLabel: actionIconName, - actions: , - children: comment.comment.trim().length > 0 && ( - + actions: , + children: attachment.comment.trim().length > 0 && ( + ), }, ]; diff --git a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/alert.tsx b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/alert.tsx index 9a405d8b0365d..4f0bc1bb032e2 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/alert.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/alert.tsx @@ -34,12 +34,12 @@ type BuilderArgs = Pick< | 'userProfiles' | 'handleDeleteComment' | 'loadingCommentIds' -> & { comment: SnakeToCamelCase }; +> & { attachment: SnakeToCamelCase }; const getSingleAlertUserAction = ({ userAction, userProfiles, - comment, + attachment, alertData, loadingAlertData, loadingCommentIds, @@ -48,16 +48,16 @@ const getSingleAlertUserAction = ({ onShowAlertDetails, handleDeleteComment, }: BuilderArgs): EuiCommentProps[] => { - const alertId = getNonEmptyField(comment.alertId); - const alertIndex = getNonEmptyField(comment.index); + const alertId = getNonEmptyField(attachment.alertId); + const alertIndex = getNonEmptyField(attachment.index); if (!alertId || !alertIndex) { return []; } const alertField: unknown | undefined = alertData[alertId]; - const ruleId = getRuleId(comment, alertField); - const ruleName = getRuleName(comment, alertField); + const ruleId = getRuleId(attachment, alertField); + const ruleName = getRuleName(attachment, alertField); return [ { @@ -79,7 +79,7 @@ const getSingleAlertUserAction = ({ timestamp: , timelineAvatar: 'bell', actions: ( - + handleDeleteComment(comment.id, DELETE_ALERTS_SUCCESS_TITLE(1))} - isLoading={loadingCommentIds.includes(comment.id)} + onDelete={() => handleDeleteComment(attachment.id, DELETE_ALERTS_SUCCESS_TITLE(1))} + isLoading={loadingCommentIds.includes(attachment.id)} totalAlerts={1} /> @@ -102,7 +102,7 @@ const getSingleAlertUserAction = ({ const getMultipleAlertsUserAction = ({ userAction, userProfiles, - comment, + attachment, alertData, loadingAlertData, loadingCommentIds, @@ -110,12 +110,12 @@ const getMultipleAlertsUserAction = ({ onRuleDetailsClick, handleDeleteComment, }: BuilderArgs): EuiCommentProps[] => { - if (!Array.isArray(comment.alertId)) { + if (!Array.isArray(attachment.alertId)) { return []; } - const totalAlerts = comment.alertId.length; - const { ruleId, ruleName } = getRuleInfo(comment, alertData); + const totalAlerts = attachment.alertId.length; + const { ruleId, ruleName } = getRuleInfo(attachment, alertData); return [ { @@ -138,15 +138,15 @@ const getMultipleAlertsUserAction = ({ timestamp: , timelineAvatar: 'bell', actions: ( - + - handleDeleteComment(comment.id, DELETE_ALERTS_SUCCESS_TITLE(totalAlerts)) + handleDeleteComment(attachment.id, DELETE_ALERTS_SUCCESS_TITLE(totalAlerts)) } - isLoading={loadingCommentIds.includes(comment.id)} + isLoading={loadingCommentIds.includes(attachment.id)} totalAlerts={totalAlerts} /> @@ -159,8 +159,8 @@ export const createAlertAttachmentUserActionBuilder = ( params: BuilderArgs ): ReturnType => ({ build: () => { - const { comment } = params; - const alertId = Array.isArray(comment.alertId) ? comment.alertId : [comment.alertId]; + const { attachment } = params; + const alertId = Array.isArray(attachment.alertId) ? attachment.alertId : [attachment.alertId]; if (alertId.length === 1) { return getSingleAlertUserAction(params); @@ -174,35 +174,41 @@ const getFirstItem = (items?: string | string[] | null): string | null => { return Array.isArray(items) ? items[0] : items ?? null; }; -export const getRuleId = (comment: BuilderArgs['comment'], alertData?: unknown): string | null => +export const getRuleId = ( + attachment: BuilderArgs['attachment'], + alertData?: unknown +): string | null => getRuleField({ - commentRuleField: comment?.rule?.id, + attachmentRuleField: attachment?.rule?.id, alertData, signalRuleFieldPath: 'signal.rule.id', kibanaAlertFieldPath: ALERT_RULE_UUID, }); -export const getRuleName = (comment: BuilderArgs['comment'], alertData?: unknown): string | null => +export const getRuleName = ( + attachment: BuilderArgs['attachment'], + alertData?: unknown +): string | null => getRuleField({ - commentRuleField: comment?.rule?.name, + attachmentRuleField: attachment?.rule?.name, alertData, signalRuleFieldPath: 'signal.rule.name', kibanaAlertFieldPath: ALERT_RULE_NAME, }); const getRuleField = ({ - commentRuleField, + attachmentRuleField, alertData, signalRuleFieldPath, kibanaAlertFieldPath, }: { - commentRuleField: string | string[] | null | undefined; + attachmentRuleField: string | string[] | null | undefined; alertData: unknown | undefined; signalRuleFieldPath: string; kibanaAlertFieldPath: string; }): string | null => { const field = - getNonEmptyField(commentRuleField) ?? + getNonEmptyField(attachmentRuleField) ?? getNonEmptyField(get(alertData, signalRuleFieldPath)) ?? getNonEmptyField(get(alertData, kibanaAlertFieldPath)); @@ -218,16 +224,19 @@ function getNonEmptyField(field: string | string[] | undefined | null): string | return firstItem; } -export function getRuleInfo(comment: BuilderArgs['comment'], alertData: BuilderArgs['alertData']) { - const alertId = getNonEmptyField(comment.alertId); +export function getRuleInfo( + attachment: BuilderArgs['attachment'], + alertData: BuilderArgs['alertData'] +) { + const alertId = getNonEmptyField(attachment.alertId); if (!alertId) { return { ruleId: null, ruleName: null }; } const alertField: unknown | undefined = alertData[alertId]; - const ruleId = getRuleId(comment, alertField); - const ruleName = getRuleName(comment, alertField); + const ruleId = getRuleId(attachment, alertField); + const ruleName = getRuleName(attachment, alertField); return { ruleId, ruleName }; } diff --git a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/comment.test.tsx b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/comment.test.tsx index dbbc18439e088..d89d2c4db3acd 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/comment.test.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/comment.test.tsx @@ -408,8 +408,8 @@ describe('createCommentUserActionBuilder', () => { ...builderArgs, caseData: { ...builderArgs.caseData, - comments: [alertComment], }, + attachments: [alertComment], userAction, }); @@ -432,8 +432,8 @@ describe('createCommentUserActionBuilder', () => { ...builderArgs, caseData: { ...builderArgs.caseData, - comments: [alertComment], }, + attachments: [alertComment], userAction, }); @@ -465,8 +465,8 @@ describe('createCommentUserActionBuilder', () => { ...builderArgs, caseData: { ...builderArgs.caseData, - comments: [alertComment], }, + attachments: [alertComment], userAction, }); @@ -501,14 +501,14 @@ describe('createCommentUserActionBuilder', () => { ...builderArgs, caseData: { ...builderArgs.caseData, - comments: [ - { - ...alertComment, - alertId: ['alert-id-1', 'alert-id-2'], - index: ['alert-index-1', 'alert-index-2'], - }, - ], }, + attachments: [ + { + ...alertComment, + alertId: ['alert-id-1', 'alert-id-2'], + index: ['alert-index-1', 'alert-index-2'], + }, + ], userAction, }); @@ -528,14 +528,14 @@ describe('createCommentUserActionBuilder', () => { ...builderArgs, caseData: { ...builderArgs.caseData, - comments: [ - { - ...alertComment, - alertId: ['alert-id-1', 'alert-id-2'], - index: ['alert-index-1', 'alert-index-2'], - }, - ], }, + attachments: [ + { + ...alertComment, + alertId: ['alert-id-1', 'alert-id-2'], + index: ['alert-index-1', 'alert-index-2'], + }, + ], userAction, }); @@ -564,14 +564,14 @@ describe('createCommentUserActionBuilder', () => { ...builderArgs, caseData: { ...builderArgs.caseData, - comments: [ - { - ...alertComment, - alertId: ['alert-id-1', 'alert-id-2'], - index: ['alert-index-1', 'alert-index-2'], - }, - ], }, + attachments: [ + { + ...alertComment, + alertId: ['alert-id-1', 'alert-id-2'], + index: ['alert-index-1', 'alert-index-2'], + }, + ], userAction, }); @@ -595,8 +595,8 @@ describe('createCommentUserActionBuilder', () => { ...builderArgs, caseData: { ...builderArgs.caseData, - comments: [hostIsolationComment()], }, + attachments: [hostIsolationComment()], userAction, }); @@ -623,8 +623,8 @@ describe('createCommentUserActionBuilder', () => { ...builderArgs, caseData: { ...builderArgs.caseData, - comments: [hostIsolationComment({ createdBy })], }, + attachments: [hostIsolationComment({ createdBy })], userAction, }); @@ -663,17 +663,17 @@ describe('createCommentUserActionBuilder', () => { externalReferenceAttachmentTypeRegistry, caseData: { ...builderArgs.caseData, - comments: [ - { - ...externalReferenceAttachment, - createdBy: { - username: damagedRaccoon.user.username, - fullName: damagedRaccoon.user.full_name, - email: damagedRaccoon.user.email, - }, - }, - ], }, + attachments: [ + { + ...externalReferenceAttachment, + createdBy: { + username: damagedRaccoon.user.username, + fullName: damagedRaccoon.user.full_name, + email: damagedRaccoon.user.email, + }, + }, + ], userAction, }); @@ -696,8 +696,8 @@ describe('createCommentUserActionBuilder', () => { externalReferenceAttachmentTypeRegistry, caseData: { ...builderArgs.caseData, - comments: [externalReferenceAttachment], }, + attachments: [externalReferenceAttachment], userAction, }); @@ -720,8 +720,8 @@ describe('createCommentUserActionBuilder', () => { externalReferenceAttachmentTypeRegistry, caseData: { ...builderArgs.caseData, - comments: [externalReferenceAttachment], }, + attachments: [externalReferenceAttachment], userAction, }); @@ -780,8 +780,8 @@ describe('createCommentUserActionBuilder', () => { persistableStateAttachmentTypeRegistry, caseData: { ...builderArgs.caseData, - comments: [attachment01], }, + attachments: [attachment01], userAction, }); @@ -809,8 +809,8 @@ describe('createCommentUserActionBuilder', () => { persistableStateAttachmentTypeRegistry, caseData: { ...builderArgs.caseData, - comments: [attachment02], }, + attachments: [attachment02], userAction, }); @@ -832,8 +832,8 @@ describe('createCommentUserActionBuilder', () => { persistableStateAttachmentTypeRegistry, caseData: { ...builderArgs.caseData, - comments: [persistableStateAttachment], }, + attachments: [persistableStateAttachment], userAction, }); @@ -856,8 +856,8 @@ describe('createCommentUserActionBuilder', () => { persistableStateAttachmentTypeRegistry, caseData: { ...builderArgs.caseData, - comments: [persistableStateAttachment], }, + attachments: [persistableStateAttachment], userAction, }); @@ -915,8 +915,8 @@ describe('createCommentUserActionBuilder', () => { externalReferenceAttachmentTypeRegistry, caseData: { ...builderArgs.caseData, - comments: [externalReferenceAttachment], }, + attachments: [externalReferenceAttachment], userAction, }); @@ -962,8 +962,8 @@ describe('createCommentUserActionBuilder', () => { externalReferenceAttachmentTypeRegistry, caseData: { ...builderArgs.caseData, - comments: [externalReferenceAttachment], }, + attachments: [externalReferenceAttachment], userAction, }); @@ -1018,8 +1018,8 @@ describe('createCommentUserActionBuilder', () => { externalReferenceAttachmentTypeRegistry, caseData: { ...builderArgs.caseData, - comments: [externalReferenceAttachment], }, + attachments: [externalReferenceAttachment], userAction, }); @@ -1073,8 +1073,8 @@ describe('createCommentUserActionBuilder', () => { externalReferenceAttachmentTypeRegistry, caseData: { ...builderArgs.caseData, - comments: [externalReferenceAttachment], }, + attachments: [externalReferenceAttachment], userAction, }); @@ -1149,8 +1149,8 @@ describe('createCommentUserActionBuilder', () => { externalReferenceAttachmentTypeRegistry, caseData: { ...builderArgs.caseData, - comments: [externalReferenceAttachment], }, + attachments: [externalReferenceAttachment], userAction, }); @@ -1200,8 +1200,8 @@ describe('createCommentUserActionBuilder', () => { externalReferenceAttachmentTypeRegistry, caseData: { ...builderArgs.caseData, - comments: [externalReferenceAttachment], }, + attachments: [externalReferenceAttachment], userAction, }); diff --git a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/comment.tsx b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/comment.tsx index 48d00f075c81f..4b2875836a7bc 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/comment.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/comment.tsx @@ -148,7 +148,7 @@ const getCreateCommentUserAction = ({ caseData, externalReferenceAttachmentTypeRegistry, persistableStateAttachmentTypeRegistry, - comment, + attachment, commentRefs, manageMarkdownEditIds, selectedOutlineCommentId, @@ -166,21 +166,21 @@ const getCreateCommentUserAction = ({ actionsNavigation, }: { userAction: SnakeToCamelCase; - comment: AttachmentUI; + attachment: AttachmentUI; } & Omit< UserActionBuilderArgs, 'comments' | 'index' | 'handleOutlineComment' | 'currentUserProfile' >): EuiCommentProps[] => { - switch (comment.type) { + switch (attachment.type) { case AttachmentType.user: const userBuilder = createUserAttachmentUserActionBuilder({ appId, userProfiles, - comment, - outlined: comment.id === selectedOutlineCommentId, - isEdit: manageMarkdownEditIds.includes(comment.id), + attachment, + outlined: attachment.id === selectedOutlineCommentId, + isEdit: manageMarkdownEditIds.includes(attachment.id), commentRefs, - isLoading: loadingCommentIds.includes(comment.id), + isLoading: loadingCommentIds.includes(attachment.id), caseId: caseData.id, euiTheme, handleManageMarkdownEditId, @@ -195,7 +195,7 @@ const getCreateCommentUserAction = ({ const alertBuilder = createAlertAttachmentUserActionBuilder({ userProfiles, alertData, - comment, + attachment, userAction, getRuleDetailsHref, loadingAlertData, @@ -211,7 +211,7 @@ const getCreateCommentUserAction = ({ const actionBuilder = createActionAttachmentUserActionBuilder({ userProfiles, userAction, - comment, + attachment, actionsNavigation, }); @@ -221,10 +221,10 @@ const getCreateCommentUserAction = ({ const externalReferenceBuilder = createExternalReferenceAttachmentUserActionBuilder({ userAction, userProfiles, - comment, + attachment, externalReferenceAttachmentTypeRegistry, caseData, - isLoading: loadingCommentIds.includes(comment.id), + isLoading: loadingCommentIds.includes(attachment.id), handleDeleteComment, }); @@ -234,10 +234,10 @@ const getCreateCommentUserAction = ({ const persistableBuilder = createPersistableStateAttachmentUserActionBuilder({ userAction, userProfiles, - comment, + attachment, persistableStateAttachmentTypeRegistry, caseData, - isLoading: loadingCommentIds.includes(comment.id), + isLoading: loadingCommentIds.includes(attachment.id), handleDeleteComment, }); @@ -273,13 +273,14 @@ export const createCommentUserActionBuilder: UserActionBuilder = ({ handleOutlineComment, actionsNavigation, caseConnectors, + attachments, }) => ({ build: () => { - const commentUserAction = userAction as SnakeToCamelCase; + const attachmentUserAction = userAction as SnakeToCamelCase; - if (commentUserAction.action === UserActionActions.delete) { + if (attachmentUserAction.action === UserActionActions.delete) { return getDeleteCommentUserAction({ - userAction: commentUserAction, + userAction: attachmentUserAction, caseData, handleOutlineComment, userProfiles, @@ -288,22 +289,22 @@ export const createCommentUserActionBuilder: UserActionBuilder = ({ }); } - const comment = caseData.comments.find((c) => c.id === commentUserAction.commentId); + const attachment = attachments.find((c) => c.id === attachmentUserAction.commentId); - if (comment == null) { + if (attachment == null) { return []; } - if (commentUserAction.action === UserActionActions.create) { + if (attachmentUserAction.action === UserActionActions.create) { const commentAction = getCreateCommentUserAction({ appId, caseData, casesConfiguration, userProfiles, - userAction: commentUserAction, + userAction: attachmentUserAction, externalReferenceAttachmentTypeRegistry, persistableStateAttachmentTypeRegistry, - comment, + attachment, commentRefs, manageMarkdownEditIds, selectedOutlineCommentId, @@ -320,6 +321,7 @@ export const createCommentUserActionBuilder: UserActionBuilder = ({ handleManageQuote, actionsNavigation, caseConnectors, + attachments, }); return commentAction; diff --git a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/external_reference.tsx b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/external_reference.tsx index 2ea7e3af6fae6..14863fffe7082 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/external_reference.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/external_reference.tsx @@ -18,14 +18,14 @@ type BuilderArgs = Pick< | 'handleDeleteComment' | 'userProfiles' > & { - comment: SnakeToCamelCase; + attachment: SnakeToCamelCase; isLoading: boolean; }; export const createExternalReferenceAttachmentUserActionBuilder = ({ userAction, userProfiles, - comment, + attachment, externalReferenceAttachmentTypeRegistry, caseData, isLoading, @@ -34,15 +34,15 @@ export const createExternalReferenceAttachmentUserActionBuilder = ({ return createRegisteredAttachmentUserActionBuilder({ userAction, userProfiles, - comment, + attachment, registry: externalReferenceAttachmentTypeRegistry, caseData, handleDeleteComment, isLoading, - getId: () => comment.externalReferenceAttachmentTypeId, + getId: () => attachment.externalReferenceAttachmentTypeId, getAttachmentViewProps: () => ({ - externalReferenceId: comment.externalReferenceId, - externalReferenceMetadata: comment.externalReferenceMetadata, + externalReferenceId: attachment.externalReferenceId, + externalReferenceMetadata: attachment.externalReferenceMetadata, }), }); }; diff --git a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/persistable_state.tsx b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/persistable_state.tsx index 0443f67612c4a..3c358925f15a1 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/persistable_state.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/persistable_state.tsx @@ -18,14 +18,14 @@ type BuilderArgs = Pick< | 'handleDeleteComment' | 'userProfiles' > & { - comment: SnakeToCamelCase; + attachment: SnakeToCamelCase; isLoading: boolean; }; export const createPersistableStateAttachmentUserActionBuilder = ({ userAction, userProfiles, - comment, + attachment, persistableStateAttachmentTypeRegistry, caseData, isLoading, @@ -34,15 +34,15 @@ export const createPersistableStateAttachmentUserActionBuilder = ({ return createRegisteredAttachmentUserActionBuilder({ userAction, userProfiles, - comment, + attachment, registry: persistableStateAttachmentTypeRegistry, caseData, handleDeleteComment, isLoading, - getId: () => comment.persistableStateAttachmentTypeId, + getId: () => attachment.persistableStateAttachmentTypeId, getAttachmentViewProps: () => ({ - persistableStateAttachmentTypeId: comment.persistableStateAttachmentTypeId, - persistableStateAttachmentState: comment.persistableStateAttachmentState, + persistableStateAttachmentTypeId: attachment.persistableStateAttachmentTypeId, + persistableStateAttachmentState: attachment.persistableStateAttachmentState, }), }); }; diff --git a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/registered_attachments.test.tsx b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/registered_attachments.test.tsx index 0f485845fcd36..e73dd7e8b18d7 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/registered_attachments.test.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/registered_attachments.test.tsx @@ -58,7 +58,7 @@ describe('createRegisteredAttachmentUserActionBuilder', () => { registry.register(item); - const comment = builderArgs.comments[0]; + const attachment = builderArgs.attachments[0]; const userActionBuilderArgs = { userAction: builderArgs.userAction, @@ -68,7 +68,7 @@ describe('createRegisteredAttachmentUserActionBuilder', () => { getId, getAttachmentViewProps, isLoading: false, - comment, + attachment, registry, }; @@ -97,7 +97,7 @@ describe('createRegisteredAttachmentUserActionBuilder', () => { expect(getAttachmentViewProps).toHaveBeenCalled(); expect(getAttachmentViewObject).toBeCalledWith({ ...viewProps, - attachmentId: comment.id, + attachmentId: attachment.id, caseData: { id: builderArgs.caseData.id, title: builderArgs.caseData.title }, }); }); diff --git a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/registered_attachments.tsx b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/registered_attachments.tsx index 49056c7b0900b..47975f901b7d8 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/registered_attachments.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/registered_attachments.tsx @@ -41,7 +41,7 @@ type BuilderArgs = Pick< UserActionBuilderArgs, 'userAction' | 'caseData' | 'handleDeleteComment' | 'userProfiles' > & { - comment: SnakeToCamelCase; + attachment: SnakeToCamelCase; registry: R; isLoading: boolean; getId: () => string; @@ -82,7 +82,7 @@ export const createRegisteredAttachmentUserActionBuilder = < >({ userAction, userProfiles, - comment, + attachment, registry, caseData, isLoading, @@ -98,7 +98,10 @@ export const createRegisteredAttachmentUserActionBuilder = < return [ { username: ( - + ), event: ( <> @@ -106,8 +109,8 @@ export const createRegisteredAttachmentUserActionBuilder = < {attachmentTypeId} ), - className: `comment-${comment.type}-not-found`, - 'data-test-subj': `comment-${comment.type}-not-found`, + className: `comment-${attachment.type}-not-found`, + 'data-test-subj': `comment-${attachment.type}-not-found`, timestamp: , children: ( @@ -120,7 +123,7 @@ export const createRegisteredAttachmentUserActionBuilder = < const props = { ...getAttachmentViewProps(), - attachmentId: comment.id, + attachmentId: attachment.id, caseData: { id: caseData.id, title: caseData.title }, }; @@ -135,30 +138,33 @@ export const createRegisteredAttachmentUserActionBuilder = < return [ { username: ( - + ), - className: `comment-${comment.type}-attachment-${attachmentTypeId}`, + className: `comment-${attachment.type}-attachment-${attachmentTypeId}`, event: attachmentViewObject.event, - 'data-test-subj': `comment-${comment.type}-${attachmentTypeId}`, + 'data-test-subj': `comment-${attachment.type}-${attachmentTypeId}`, timestamp: , timelineAvatar: attachmentViewObject.timelineAvatar, actions: ( - + {visiblePrimaryActions.map( (action) => (action.type === AttachmentActionType.BUTTON && ( )) || @@ -166,7 +172,7 @@ export const createRegisteredAttachmentUserActionBuilder = < )} handleDeleteComment(comment.id, DELETE_REGISTERED_ATTACHMENT)} + onDelete={() => handleDeleteComment(attachment.id, DELETE_REGISTERED_ATTACHMENT)} registeredAttachmentActions={[...nonVisiblePrimaryActions, ...nonPrimaryActions]} hideDefaultActions={!!attachmentViewObject.hideDefaultActions} /> diff --git a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/user.tsx b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/user.tsx index 67366ee4a81d3..5027207a757a8 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/user.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/user_actions/comment/user.tsx @@ -34,7 +34,7 @@ type BuilderArgs = Pick< | 'appId' | 'euiTheme' > & { - comment: SnakeToCamelCase; + attachment: SnakeToCamelCase; caseId: string; outlined: boolean; isEdit: boolean; @@ -66,7 +66,7 @@ const hasDraftComment = ( export const createUserAttachmentUserActionBuilder = ({ appId, - comment, + attachment, userProfiles, outlined, isEdit, @@ -81,33 +81,39 @@ export const createUserAttachmentUserActionBuilder = ({ }: BuilderArgs): ReturnType => ({ build: () => [ { - username: , - 'data-test-subj': `comment-create-action-${comment.id}`, + username: ( + + ), + 'data-test-subj': `comment-create-action-${attachment.id}`, timestamp: ( - + ), className: classNames('userAction__comment', { outlined, isEdit, draftFooter: - !isEdit && !isLoading && hasDraftComment(appId, caseId, comment.id, comment.comment), + !isEdit && + !isLoading && + hasDraftComment(appId, caseId, attachment.id, attachment.comment), }), children: ( <> (commentRefs.current[comment.id] = element)} - id={comment.id} - content={comment.comment} + key={isEdit ? attachment.id : undefined} + ref={(element) => (commentRefs.current[attachment.id] = element)} + id={attachment.id} + content={attachment.comment} isEditable={isEdit} caseId={caseId} onChangeEditable={handleManageMarkdownEditId} onSaveContent={handleSaveComment.bind(null, { - id: comment.id, - version: comment.version, + id: attachment.id, + version: attachment.version, })} /> - {!isEdit && !isLoading && hasDraftComment(appId, caseId, comment.id, comment.comment) ? ( + {!isEdit && + !isLoading && + hasDraftComment(appId, caseId, attachment.id, attachment.comment) ? ( {i18n.UNSAVED_DRAFT_COMMENT} @@ -119,16 +125,16 @@ export const createUserAttachmentUserActionBuilder = ({ ), timelineAvatar: ( - + ), actions: ( - + handleManageMarkdownEditId(comment.id)} - onDelete={() => handleDeleteComment(comment.id, i18n.DELETE_COMMENT_SUCCESS_TITLE)} - onQuote={() => handleManageQuote(comment.comment)} + commentContent={attachment.comment} + onEdit={() => handleManageMarkdownEditId(attachment.id)} + onDelete={() => handleDeleteComment(attachment.id, i18n.DELETE_COMMENT_SUCCESS_TITLE)} + onQuote={() => handleManageQuote(attachment.comment)} /> ), diff --git a/x-pack/platform/plugins/shared/cases/public/components/user_actions/index.tsx b/x-pack/platform/plugins/shared/cases/public/components/user_actions/index.tsx index 793405276cdb4..8dadf97244927 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/user_actions/index.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/user_actions/index.tsx @@ -82,6 +82,7 @@ export const UserActions = React.memo((props: UserActionTreeProps) => { const { infiniteCaseUserActions, + infiniteLatestAttachments, isLoadingInfiniteUserActions, hasNextPage, fetchNextPage, @@ -95,11 +96,12 @@ export const UserActions = React.memo((props: UserActionTreeProps) => { const { euiTheme } = useEuiTheme(); - const { isLoadingLastPageUserActions, lastPageUserActions } = useLastPageUserActions({ - userActivityQueryParams, - caseId: caseData.id, - lastPage, - }); + const { isLoadingLastPageUserActions, lastPageUserActions, lastPageAttachments } = + useLastPageUserActions({ + userActivityQueryParams, + caseId: caseData.id, + lastPage, + }); const alertIdsWithoutRuleInfo = useMemo( () => getManualAlertIdsWithNoRuleId(caseData.comments), @@ -180,6 +182,7 @@ export const UserActions = React.memo((props: UserActionTreeProps) => { { { persistableStateAttachmentTypeRegistry, caseData: basicCase, casesConfiguration: casesConfigurationsMock, - comments: basicCase.comments, + attachments: basicCase.comments, index: 0, alertData, commentRefs, diff --git a/x-pack/platform/plugins/shared/cases/public/components/user_actions/types.ts b/x-pack/platform/plugins/shared/cases/public/components/user_actions/types.ts index fa63971c8ef24..8cde0550d4846 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/user_actions/types.ts +++ b/x-pack/platform/plugins/shared/cases/public/components/user_actions/types.ts @@ -60,7 +60,7 @@ export interface UserActionBuilderArgs { persistableStateAttachmentTypeRegistry: PersistableStateAttachmentTypeRegistry; caseConnectors: CaseConnectors; userAction: UserActionUI; - comments: AttachmentUI[]; + attachments: AttachmentUI[]; index: number; commentRefs: React.MutableRefObject< Record diff --git a/x-pack/platform/plugins/shared/cases/public/components/user_actions/use_user_actions_last_page.tsx b/x-pack/platform/plugins/shared/cases/public/components/user_actions/use_user_actions_last_page.tsx index 32fc45aa433ab..0134619c43c71 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/user_actions/use_user_actions_last_page.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/user_actions/use_user_actions_last_page.tsx @@ -7,7 +7,7 @@ import { useMemo } from 'react'; -import type { UserActionUI } from '../../containers/types'; +import type { AttachmentUI, UserActionUI } from '../../containers/types'; import { useFindCaseUserActions } from '../../containers/use_find_case_user_actions'; import type { UserActivityParams } from '../user_actions_activity_bar/types'; @@ -25,16 +25,23 @@ export const useLastPageUserActions = ({ const { data: lastPageUserActionsData, isLoading: isLoadingLastPageUserActions } = useFindCaseUserActions(caseId, { ...userActivityQueryParams, page: lastPage }, lastPage > 1); - const lastPageUserActions = useMemo(() => { + const { userActions, latestAttachments } = useMemo<{ + userActions: UserActionUI[]; + latestAttachments: AttachmentUI[]; + }>(() => { if (isLoadingLastPageUserActions || !lastPageUserActionsData) { - return []; + return { userActions: [], latestAttachments: [] }; } - return lastPageUserActionsData.userActions; + return { + userActions: lastPageUserActionsData.userActions, + latestAttachments: lastPageUserActionsData.latestAttachments, + }; }, [lastPageUserActionsData, isLoadingLastPageUserActions]); return { isLoadingLastPageUserActions, - lastPageUserActions, + lastPageUserActions: userActions, + lastPageAttachments: latestAttachments, }; }; diff --git a/x-pack/platform/plugins/shared/cases/public/components/user_actions/use_user_actions_pagination.tsx b/x-pack/platform/plugins/shared/cases/public/components/user_actions/use_user_actions_pagination.tsx index bdaaa68de0157..f33fcfa1ca0b0 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/user_actions/use_user_actions_pagination.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/user_actions/use_user_actions_pagination.tsx @@ -8,7 +8,7 @@ import { useMemo } from 'react'; import { useInfiniteFindCaseUserActions } from '../../containers/use_infinite_find_case_user_actions'; -import type { UserActionUI } from '../../containers/types'; +import type { AttachmentUI, UserActionUI } from '../../containers/types'; import type { UserActivityParams } from '../user_actions_activity_bar/types'; interface UserActionsPagination { @@ -32,23 +32,32 @@ export const useUserActionsPagination = ({ const showBottomList = lastPage > 1; - const infiniteCaseUserActions = useMemo(() => { + const infiniteCaseUserActions = useMemo<{ + userActions: UserActionUI[]; + latestAttachments: AttachmentUI[]; + }>(() => { if (!caseInfiniteUserActionsData?.pages?.length || isLoadingInfiniteUserActions) { - return []; + return { userActions: [], latestAttachments: [] }; } const userActionsData: UserActionUI[] = []; + const latestAttachments: AttachmentUI[] = []; + // TODO: looks like it can be done in one loop caseInfiniteUserActionsData.pages.forEach((page) => userActionsData.push(...page.userActions)); + caseInfiniteUserActionsData.pages.forEach((page) => + latestAttachments.push(...page.latestAttachments) + ); - return userActionsData; + return { userActions: userActionsData, latestAttachments }; }, [caseInfiniteUserActionsData, isLoadingInfiniteUserActions]); return { lastPage, showBottomList, isLoadingInfiniteUserActions, - infiniteCaseUserActions, + infiniteCaseUserActions: infiniteCaseUserActions.userActions, + infiniteLatestAttachments: infiniteCaseUserActions.latestAttachments, hasNextPage, fetchNextPage, isFetchingNextPage, diff --git a/x-pack/platform/plugins/shared/cases/public/components/user_actions/user_actions_list.tsx b/x-pack/platform/plugins/shared/cases/public/components/user_actions/user_actions_list.tsx index 954d811c48aa1..7956d5334b3a9 100644 --- a/x-pack/platform/plugins/shared/cases/public/components/user_actions/user_actions_list.tsx +++ b/x-pack/platform/plugins/shared/cases/public/components/user_actions/user_actions_list.tsx @@ -11,7 +11,7 @@ import { EuiCommentList, useEuiTheme } from '@elastic/eui'; import React, { useMemo, useEffect, useState } from 'react'; import { css } from '@emotion/react'; -import type { UserActionUI } from '../../containers/types'; +import type { AttachmentUI, UserActionUI } from '../../containers/types'; import type { UserActionBuilderArgs, UserActionTreeProps } from './types'; import { isUserActionTypeSupported } from './helpers'; import { useCasesContext } from '../cases_context/use_cases_context'; @@ -66,6 +66,7 @@ export type UserActionListProps = Omit< > & Pick & { caseUserActions: UserActionUI[]; + attachments: AttachmentUI[]; loadingAlertData: boolean; manualAlertsData: Record; bottomActions?: EuiCommentProps[]; @@ -75,6 +76,7 @@ export type UserActionListProps = Omit< export const UserActionsList = React.memo( ({ caseUserActions, + attachments, caseConnectors, userProfiles, currentUserProfile, @@ -113,15 +115,15 @@ export const UserActionsList = React.memo( return []; } - return caseUserActions.reduce((comments, userAction, index) => { + return caseUserActions.reduce((userActions, userAction, index) => { if (!isUserActionTypeSupported(userAction.type)) { - return comments; + return userActions; } const builder = builderMap[userAction.type]; if (builder == null) { - return comments; + return userActions; } const userActionBuilder = builder({ @@ -134,7 +136,7 @@ export const UserActionsList = React.memo( userAction, userProfiles, currentUserProfile, - comments: caseData?.comments, + attachments, index, commentRefs, manageMarkdownEditIds, @@ -153,7 +155,7 @@ export const UserActionsList = React.memo( getRuleDetailsHref, onRuleDetailsClick, }); - return [...comments, ...userActionBuilder.build()]; + return [...userActions, ...userActionBuilder.build()]; }, []); }, [ caseUserActions, @@ -165,6 +167,7 @@ export const UserActionsList = React.memo( persistableStateAttachmentTypeRegistry, userProfiles, currentUserProfile, + attachments, commentRefs, manageMarkdownEditIds, selectedOutlineCommentId, diff --git a/x-pack/platform/plugins/shared/cases/public/containers/__mocks__/api.ts b/x-pack/platform/plugins/shared/cases/public/containers/__mocks__/api.ts index ab12561e2c733..f60b0306420ed 100644 --- a/x-pack/platform/plugins/shared/cases/public/containers/__mocks__/api.ts +++ b/x-pack/platform/plugins/shared/cases/public/containers/__mocks__/api.ts @@ -51,12 +51,6 @@ import type { UserProfile } from '@kbn/security-plugin/common'; import { userProfiles } from '../user_profiles/api.mock'; import { getCaseConnectorsMockResponse } from '../../common/mock/connectors'; -export const getCase = async ( - caseId: string, - includeComments: boolean = true, - signal: AbortSignal -): Promise => Promise.resolve(basicCase); - export const resolveCase = async ( caseId: string, includeComments: boolean = true, diff --git a/x-pack/platform/plugins/shared/cases/public/containers/api.test.tsx b/x-pack/platform/plugins/shared/cases/public/containers/api.test.tsx index 2934c4d1f3432..4854acd2b8a9f 100644 --- a/x-pack/platform/plugins/shared/cases/public/containers/api.test.tsx +++ b/x-pack/platform/plugins/shared/cases/public/containers/api.test.tsx @@ -22,7 +22,6 @@ import { deleteCases, deleteComment, getActionLicense, - getCase, getCases, findCaseUserActions, getTags, @@ -135,34 +134,6 @@ describe('Cases API', () => { }); }); - describe('getCase', () => { - beforeEach(() => { - fetchMock.mockClear(); - fetchMock.mockResolvedValue(basicCaseSnake); - }); - const data = basicCase.id; - - it('should be called with correct check url, method, signal', async () => { - await getCase(data, true, abortCtrl.signal); - expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/${basicCase.id}`, { - method: 'GET', - query: { includeComments: true }, - signal: abortCtrl.signal, - }); - }); - - it('should return correct response', async () => { - const resp = await getCase(data, true, abortCtrl.signal); - expect(resp).toEqual(basicCase); - }); - - it('should not covert to camel case registered attachments', async () => { - fetchMock.mockResolvedValue(caseWithRegisteredAttachmentsSnake); - const resp = await getCase(data, true, abortCtrl.signal); - expect(resp).toEqual(caseWithRegisteredAttachments); - }); - }); - describe('resolveCase', () => { const aliasTargetId = '12345'; const basicResolveCase = { @@ -180,7 +151,9 @@ describe('Cases API', () => { await resolveCase({ caseId, signal: abortCtrl.signal }); expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/${caseId}/resolve`, { method: 'GET', - query: { includeComments: true }, + query: { + includeComments: false, + }, signal: abortCtrl.signal, }); }); @@ -540,6 +513,7 @@ describe('Cases API', () => { perPage: 10, total: 30, userActions: [...caseUserActionsWithRegisteredAttachmentsSnake], + latestAttachments: [], }; const filterActionType: CaseUserActionTypeWithAll = 'all'; const sortOrder: 'asc' | 'desc' = 'asc'; @@ -557,16 +531,19 @@ describe('Cases API', () => { it('should be called with correct check url, method, signal', async () => { await findCaseUserActions(basicCase.id, params, abortCtrl.signal); - expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/${basicCase.id}/user_actions/_find`, { - method: 'GET', - signal: abortCtrl.signal, - query: { - types: [], - sortOrder: 'asc', - page: 1, - perPage: 10, - }, - }); + expect(fetchMock).toHaveBeenCalledWith( + `${CASES_INTERNAL_URL}/${basicCase.id}/user_actions/_find`, + { + method: 'GET', + signal: abortCtrl.signal, + query: { + types: [], + sortOrder: 'asc', + page: 1, + perPage: 10, + }, + } + ); }); it('should be called with action type user action and desc sort order', async () => { @@ -575,30 +552,36 @@ describe('Cases API', () => { { type: 'action', sortOrder: 'desc', page: 2, perPage: 15 }, abortCtrl.signal ); - expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/${basicCase.id}/user_actions/_find`, { - method: 'GET', - signal: abortCtrl.signal, - query: { - types: ['action'], - sortOrder: 'desc', - page: 2, - perPage: 15, - }, - }); + expect(fetchMock).toHaveBeenCalledWith( + `${CASES_INTERNAL_URL}/${basicCase.id}/user_actions/_find`, + { + method: 'GET', + signal: abortCtrl.signal, + query: { + types: ['action'], + sortOrder: 'desc', + page: 2, + perPage: 15, + }, + } + ); }); it('should be called with user type user action and desc sort order', async () => { await findCaseUserActions(basicCase.id, { ...params, type: 'user' }, abortCtrl.signal); - expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/${basicCase.id}/user_actions/_find`, { - method: 'GET', - signal: abortCtrl.signal, - query: { - types: ['user'], - sortOrder: 'asc', - page: 1, - perPage: 10, - }, - }); + expect(fetchMock).toHaveBeenCalledWith( + `${CASES_INTERNAL_URL}/${basicCase.id}/user_actions/_find`, + { + method: 'GET', + signal: abortCtrl.signal, + query: { + types: ['user'], + sortOrder: 'asc', + page: 1, + perPage: 10, + }, + } + ); }); it('should return correct response', async () => { diff --git a/x-pack/platform/plugins/shared/cases/public/containers/api.ts b/x-pack/platform/plugins/shared/cases/public/containers/api.ts index 4216421892b8c..7aed7381ce35c 100644 --- a/x-pack/platform/plugins/shared/cases/public/containers/api.ts +++ b/x-pack/platform/plugins/shared/cases/public/containers/api.ts @@ -19,19 +19,18 @@ import type { CasesFindResponse, CaseUserActionStatsResponse, GetCaseConnectorsResponse, - UserActionFindResponse, SingleCaseMetricsResponse, CustomFieldPutRequest, CasesSimilarResponse, AddObservableRequest, UpdateObservableRequest, + UserActionInternalFindResponse, } from '../../common/types/api'; import type { CaseConnectors, CaseUpdateRequest, FetchCasesProps, ResolvedCase, - FindCaseUserActions, CaseUserActionTypeWithAll, CaseUserActionsStats, CaseUsers, @@ -41,6 +40,7 @@ import type { CaseUICustomField, SimilarCasesProps, CasesSimilarResponseUI, + InternalFindCaseUserActions, } from '../../common/ui/types'; import { SortFieldCase } from '../../common/ui/types'; import { @@ -81,6 +81,7 @@ import { convertCasesToCamelCase, convertCaseResolveToCamelCase, convertSimilarCasesToCamel, + convertAttachmentsToCamelCase, } from '../api/utils'; import type { @@ -105,37 +106,18 @@ import { } from './utils'; import { decodeCasesFindResponse, decodeCasesSimilarResponse } from '../api/decoders'; -export const getCase = async ( - caseId: string, - includeComments: boolean = true, - signal: AbortSignal -): Promise => { - const response = await KibanaServices.get().http.fetch(getCaseDetailsUrl(caseId), { - method: 'GET', - query: { - includeComments, - }, - signal, - }); - return convertCaseToCamelCase(decodeCaseResponse(response)); -}; - export const resolveCase = async ({ caseId, - includeComments = true, signal, }: { caseId: string; - includeComments?: boolean; signal?: AbortSignal; }): Promise => { const response = await KibanaServices.get().http.fetch( `${getCaseDetailsUrl(caseId)}/resolve`, { method: 'GET', - query: { - includeComments, - }, + query: { includeComments: false }, signal, } ); @@ -211,7 +193,7 @@ export const findCaseUserActions = async ( perPage: number; }, signal?: AbortSignal -): Promise => { +): Promise => { const query = { types: params.type !== 'all' ? [params.type] : [], sortOrder: params.sortOrder, @@ -219,7 +201,7 @@ export const findCaseUserActions = async ( perPage: params.perPage, }; - const response = await KibanaServices.get().http.fetch( + const response = await KibanaServices.get().http.fetch( getCaseFindUserActionsUrl(caseId), { method: 'GET', @@ -233,6 +215,7 @@ export const findCaseUserActions = async ( userActions: convertUserActionsToCamelCase( decodeCaseUserActionsResponse(response.userActions) ) as UserActionUI[], + latestAttachments: convertAttachmentsToCamelCase(response.latestAttachments), }; }; diff --git a/x-pack/platform/plugins/shared/cases/public/containers/mock.ts b/x-pack/platform/plugins/shared/cases/public/containers/mock.ts index 5253e425a2a88..b6ecc5e3ca36e 100644 --- a/x-pack/platform/plugins/shared/cases/public/containers/mock.ts +++ b/x-pack/platform/plugins/shared/cases/public/containers/mock.ts @@ -38,7 +38,6 @@ import type { CasesMetrics, ExternalReferenceAttachmentUI, PersistableStateAttachmentUI, - FindCaseUserActions, CaseUsers, CaseUserActionsStats, CasesFindResponseUI, @@ -49,6 +48,7 @@ import type { CasesConfigurationUITemplate, CasesSimilarResponseUI, ObservableUI, + InternalFindCaseUserActions, } from '../../common/ui/types'; import { CaseMetricsFeature } from '../../common/types/api'; import { OBSERVABLE_TYPE_IPV4, SECURITY_SOLUTION_OWNER } from '../../common/constants'; @@ -974,11 +974,12 @@ export const caseUserActionsWithRegisteredAttachments: UserActionUI[] = [ }, ]; -export const findCaseUserActionsResponse: FindCaseUserActions = { +export const findCaseUserActionsResponse: InternalFindCaseUserActions = { page: 1, perPage: 10, total: 30, userActions: [...caseUserActionsWithRegisteredAttachments], + latestAttachments: [], }; export const getCaseUserActionsStatsResponse: CaseUserActionsStats = { @@ -1323,3 +1324,16 @@ export const mockObservables: ObservableUI[] = [ updatedAt: '2024-12-11', }, ]; + +export const mockSimilarObservables = [ + { + value: '127.0.0.1', + typeKey: OBSERVABLE_TYPE_IPV4.key, + typeLabel: OBSERVABLE_TYPE_IPV4.label, + }, + { + value: '10.0.0.1', + typeKey: OBSERVABLE_TYPE_IPV4.key, + typeLabel: OBSERVABLE_TYPE_IPV4.label, + }, +]; diff --git a/x-pack/platform/plugins/shared/cases/public/containers/types.ts b/x-pack/platform/plugins/shared/cases/public/containers/types.ts index d23d18c6e7896..ec98d24b73103 100644 --- a/x-pack/platform/plugins/shared/cases/public/containers/types.ts +++ b/x-pack/platform/plugins/shared/cases/public/containers/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; export * from '../../common/ui'; diff --git a/x-pack/platform/plugins/shared/cases/public/containers/use_find_case_user_actions.test.tsx b/x-pack/platform/plugins/shared/cases/public/containers/use_find_case_user_actions.test.tsx index 7dfaa1ff146ee..dc4fbb4402672 100644 --- a/x-pack/platform/plugins/shared/cases/public/containers/use_find_case_user_actions.test.tsx +++ b/x-pack/platform/plugins/shared/cases/public/containers/use_find_case_user_actions.test.tsx @@ -52,6 +52,7 @@ describe('UseFindCaseUserActions', () => { expect.objectContaining({ ...initialData, data: { + latestAttachments: [], userActions: [...findCaseUserActionsResponse.userActions], total: 30, perPage: 10, diff --git a/x-pack/platform/plugins/shared/cases/public/containers/use_find_case_user_actions.tsx b/x-pack/platform/plugins/shared/cases/public/containers/use_find_case_user_actions.tsx index 41845882ff651..6b8a8e4df8049 100644 --- a/x-pack/platform/plugins/shared/cases/public/containers/use_find_case_user_actions.tsx +++ b/x-pack/platform/plugins/shared/cases/public/containers/use_find_case_user_actions.tsx @@ -6,7 +6,7 @@ */ import { useQuery } from '@tanstack/react-query'; -import type { FindCaseUserActions, CaseUserActionTypeWithAll } from '../../common/ui/types'; +import type { CaseUserActionTypeWithAll, InternalFindCaseUserActions } from '../../common/ui/types'; import { findCaseUserActions } from './api'; import type { ServerError } from '../types'; import { useCasesToast } from '../common/use_cases_toast'; @@ -25,7 +25,7 @@ export const useFindCaseUserActions = ( ) => { const { showErrorToast } = useCasesToast(); - return useQuery( + return useQuery( casesQueriesKeys.caseUserActions(caseId, params), async ({ signal }) => findCaseUserActions(caseId, params, signal), { diff --git a/x-pack/platform/plugins/shared/cases/public/containers/use_get_case.tsx b/x-pack/platform/plugins/shared/cases/public/containers/use_get_case.tsx index 4697fde760780..1067b3c72ea17 100644 --- a/x-pack/platform/plugins/shared/cases/public/containers/use_get_case.tsx +++ b/x-pack/platform/plugins/shared/cases/public/containers/use_get_case.tsx @@ -17,7 +17,7 @@ export const useGetCase = (caseId: string) => { const toasts = useToasts(); return useQuery( casesQueriesKeys.case(caseId), - ({ signal }) => resolveCase({ caseId, includeComments: true, signal }), + ({ signal }) => resolveCase({ caseId, signal }), { onError: (error: ServerError) => { if (error.name !== 'AbortError') { diff --git a/x-pack/platform/plugins/shared/cases/public/containers/use_infinite_find_case_user_actions.test.tsx b/x-pack/platform/plugins/shared/cases/public/containers/use_infinite_find_case_user_actions.test.tsx index 19a7f2b9edc3f..d60a521390470 100644 --- a/x-pack/platform/plugins/shared/cases/public/containers/use_infinite_find_case_user_actions.test.tsx +++ b/x-pack/platform/plugins/shared/cases/public/containers/use_infinite_find_case_user_actions.test.tsx @@ -55,6 +55,7 @@ describe('UseInfiniteFindCaseUserActions', () => { data: { pages: [ { + latestAttachments: [], userActions: [...findCaseUserActionsResponse.userActions], total: 30, perPage: 10, diff --git a/x-pack/platform/plugins/shared/cases/public/containers/use_infinite_find_case_user_actions.tsx b/x-pack/platform/plugins/shared/cases/public/containers/use_infinite_find_case_user_actions.tsx index 2d4f0056849db..e769de7823d63 100644 --- a/x-pack/platform/plugins/shared/cases/public/containers/use_infinite_find_case_user_actions.tsx +++ b/x-pack/platform/plugins/shared/cases/public/containers/use_infinite_find_case_user_actions.tsx @@ -6,7 +6,7 @@ */ import { useInfiniteQuery } from '@tanstack/react-query'; -import type { FindCaseUserActions, CaseUserActionTypeWithAll } from '../../common/ui/types'; +import type { InternalFindCaseUserActions, CaseUserActionTypeWithAll } from '../../common/ui/types'; import { findCaseUserActions } from './api'; import type { ServerError } from '../types'; import { useCasesToast } from '../common/use_cases_toast'; @@ -25,7 +25,7 @@ export const useInfiniteFindCaseUserActions = ( const { showErrorToast } = useCasesToast(); const abortCtrlRef = new AbortController(); - return useInfiniteQuery( + return useInfiniteQuery( casesQueriesKeys.caseUserActions(caseId, params), async ({ pageParam = 1 }) => { return findCaseUserActions(caseId, { ...params, page: pageParam }, abortCtrlRef.signal); diff --git a/x-pack/platform/plugins/shared/cases/server/client/cases/similar.ts b/x-pack/platform/plugins/shared/cases/server/client/cases/similar.ts index daca8d1e6b573..08911cd6bf3df 100644 --- a/x-pack/platform/plugins/shared/cases/server/client/cases/similar.ts +++ b/x-pack/platform/plugins/shared/cases/server/client/cases/similar.ts @@ -7,6 +7,7 @@ import { intersection } from 'lodash'; import Boom from '@hapi/boom'; +import type { ObservableType } from '../../../common/types/domain/observable/v1'; import { OWNER_FIELD } from '../../../common/constants'; import type { CasesSimilarResponse, SimilarCasesSearchRequest } from '../../../common/types/api'; import { SimilarCasesSearchRequestRt, CasesSimilarResponseRt } from '../../../common/types/api'; @@ -19,7 +20,7 @@ import { Operations } from '../../authorization'; import { buildFilter, buildObservablesFieldsFilter, combineFilters } from '../utils'; import { combineFilterWithAuthorizationFilter } from '../../authorization/utils'; import type { CaseSavedObjectTransformed } from '../../common/types/case'; -import { getAvailableObservableTypesSet } from '../observable_types'; +import { getAvailableObservableTypesMap } from '../observable_types'; interface Similarity { typeKey: string; @@ -29,7 +30,7 @@ interface Similarity { const getSimilarities = ( a: CaseSavedObjectTransformed, b: CaseSavedObjectTransformed, - availableObservableTypes: Set + availableObservableTypes: Map ): Similarity[] => { const stringify = (observable: { typeKey: string; value: string }) => [observable.typeKey, observable.value].join(','); @@ -46,6 +47,7 @@ const getSimilarities = ( return { typeKey, value, + typeLabel: availableObservableTypes.get(typeKey)?.label, }; }) .filter((observable) => availableObservableTypes.has(observable.typeKey)); @@ -78,7 +80,7 @@ export const similar = async ( const paramArgs = decodeWithExcessOrThrow(SimilarCasesSearchRequestRt)(params); const retrievedCase = await caseService.getCase({ id: caseId }); - const availableObservableTypesSet = await getAvailableObservableTypesSet( + const availableObservableTypesMap = await getAvailableObservableTypesMap( casesClient, retrievedCase.attributes.owner ); @@ -95,7 +97,7 @@ export const similar = async ( const similarCasesFilter = buildObservablesFieldsFilter( retrievedCase.attributes.observables.reduce((observableMap, observable) => { // NOTE: skip non-existent observable types - if (!availableObservableTypesSet.has(observable.typeKey)) { + if (!availableObservableTypesMap.has(observable.typeKey)) { return observableMap; } @@ -144,7 +146,7 @@ export const similar = async ( cases: cases.saved_objects.map((so) => ({ ...flattenCaseSavedObject({ savedObject: so }), similarities: { - observables: getSimilarities(retrievedCase, so, availableObservableTypesSet), + observables: getSimilarities(retrievedCase, so, availableObservableTypesMap), }, })), page: cases.page, diff --git a/x-pack/platform/plugins/shared/cases/server/client/metrics/alerts/aggregations/hosts.ts b/x-pack/platform/plugins/shared/cases/server/client/metrics/alerts/aggregations/hosts.ts index b739abd848294..31c11c21b97a7 100644 --- a/x-pack/platform/plugins/shared/cases/server/client/metrics/alerts/aggregations/hosts.ts +++ b/x-pack/platform/plugins/shared/cases/server/client/metrics/alerts/aggregations/hosts.ts @@ -7,7 +7,7 @@ import { get } from 'lodash'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import type { SingleCaseMetricsResponse } from '../../../../../common/types/api'; import type { AggregationBuilder, AggregationResponse } from '../../types'; diff --git a/x-pack/platform/plugins/shared/cases/server/client/metrics/types.ts b/x-pack/platform/plugins/shared/cases/server/client/metrics/types.ts index dd832be3d93f0..c234fd4192df2 100644 --- a/x-pack/platform/plugins/shared/cases/server/client/metrics/types.ts +++ b/x-pack/platform/plugins/shared/cases/server/client/metrics/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import type { CasesMetricsFeatureField, SingleCaseMetricsFeatureField, diff --git a/x-pack/platform/plugins/shared/cases/server/client/observable_types.test.ts b/x-pack/platform/plugins/shared/cases/server/client/observable_types.test.ts index d5ba5d21cbe29..bbf47d76ea73f 100644 --- a/x-pack/platform/plugins/shared/cases/server/client/observable_types.test.ts +++ b/x-pack/platform/plugins/shared/cases/server/client/observable_types.test.ts @@ -6,18 +6,23 @@ */ import type { Configurations } from '../../common/types/domain/configure/v1'; -import { OBSERVABLE_TYPES_BUILTIN_KEYS } from '../../common/constants'; +import { OBSERVABLE_TYPES_BUILTIN } from '../../common/constants'; import { createCasesClientMock } from './mocks'; -import { getAvailableObservableTypesSet } from './observable_types'; +import { getAvailableObservableTypesMap } from './observable_types'; +import type { ObservableType } from '../../common/types/domain'; const mockCasesClient = createCasesClientMock(); -describe('getAvailableObservableTypesSet', () => { +const arrayToMap = (arr: ObservableType[]): Map => { + return new Map(arr.map((item) => [item.key, item])); +}; + +describe('getAvailableObservableTypesMap', () => { beforeEach(() => { jest.clearAllMocks(); }); - it('should return a set of available observable types', async () => { + it('should return a map of available observable types', async () => { const mockObservableTypes = [ { key: 'type1', label: 'test 1' }, { key: 'type2', label: 'test 2' }, @@ -29,9 +34,9 @@ describe('getAvailableObservableTypesSet', () => { }, ] as unknown as Configurations); - const result = await getAvailableObservableTypesSet(mockCasesClient, 'mock-owner'); + const result = await getAvailableObservableTypesMap(mockCasesClient, 'mock-owner'); - expect(result).toEqual(new Set(['type1', 'type2', ...OBSERVABLE_TYPES_BUILTIN_KEYS])); + expect(result).toEqual(arrayToMap([...OBSERVABLE_TYPES_BUILTIN, ...mockObservableTypes])); }); it('should return only built-in observable types if no types are configured', async () => { @@ -41,18 +46,18 @@ describe('getAvailableObservableTypesSet', () => { }, ] as unknown as Configurations); - const result = await getAvailableObservableTypesSet(mockCasesClient, 'mock-owner'); + const result = await getAvailableObservableTypesMap(mockCasesClient, 'mock-owner'); - expect(result).toEqual(new Set(OBSERVABLE_TYPES_BUILTIN_KEYS)); + expect(result).toEqual(arrayToMap(OBSERVABLE_TYPES_BUILTIN)); }); - it('should handle errors and return an empty set', async () => { + it('should handle errors and return an empty map', async () => { jest .mocked(mockCasesClient.configure.get) .mockRejectedValue(new Error('Failed to fetch configuration')); - const result = await getAvailableObservableTypesSet(mockCasesClient, 'mock-owner'); + const result = await getAvailableObservableTypesMap(mockCasesClient, 'mock-owner'); - expect(result).toEqual(new Set()); + expect(result).toEqual(new Map()); }); }); diff --git a/x-pack/platform/plugins/shared/cases/server/client/observable_types.ts b/x-pack/platform/plugins/shared/cases/server/client/observable_types.ts index a6183fc6833b5..426378afb490c 100644 --- a/x-pack/platform/plugins/shared/cases/server/client/observable_types.ts +++ b/x-pack/platform/plugins/shared/cases/server/client/observable_types.ts @@ -5,22 +5,35 @@ * 2.0. */ +import type { ObservableType } from '../../common/types/domain'; import { OBSERVABLE_TYPES_BUILTIN } from '../../common/constants'; import type { CasesClient } from './client'; -export const getAvailableObservableTypesSet = async (casesClient: CasesClient, owner: string) => { +export const getAvailableObservableTypes = async (casesClient: CasesClient, owner: string) => { + const configurations = await casesClient.configure.get({ + owner, + }); + const observableTypes = configurations?.[0]?.observableTypes ?? []; + + return [...observableTypes, ...OBSERVABLE_TYPES_BUILTIN]; +}; + +export const getAvailableObservableTypesMap = async ( + casesClient: CasesClient, + owner: string +): Promise> => { try { - const configurations = await casesClient.configure.get({ - owner, - }); - const observableTypes = configurations?.[0]?.observableTypes ?? []; + const observableTypes = await getAvailableObservableTypes(casesClient, owner); - const availableObservableTypesSet = new Set( - [...observableTypes, ...OBSERVABLE_TYPES_BUILTIN].map(({ key }) => key) + const availableObservableTypesSet = new Map( + [...observableTypes, ...OBSERVABLE_TYPES_BUILTIN].map((observableType) => [ + observableType.key, + observableType, + ]) ); return availableObservableTypesSet; } catch (error) { - return new Set(); + return new Map(); } }; diff --git a/x-pack/platform/plugins/shared/cases/server/client/validators.ts b/x-pack/platform/plugins/shared/cases/server/client/validators.ts index 23f26d2321e78..6e309600fcb17 100644 --- a/x-pack/platform/plugins/shared/cases/server/client/validators.ts +++ b/x-pack/platform/plugins/shared/cases/server/client/validators.ts @@ -8,7 +8,7 @@ import Boom from '@hapi/boom'; import { OBSERVABLE_TYPES_BUILTIN } from '../../common/constants'; import { type CasesClient } from './client'; -import { getAvailableObservableTypesSet } from './observable_types'; +import { getAvailableObservableTypesMap } from './observable_types'; /** * Throws an error if the request has custom fields with duplicated keys. @@ -122,7 +122,7 @@ export const validateObservableTypeKeyExists = async ( observableTypeKey: string; } ) => { - const observableTypesSet = await getAvailableObservableTypesSet(casesClient, caseOwner); + const observableTypesSet = await getAvailableObservableTypesMap(casesClient, caseOwner); if (!observableTypesSet.has(observableTypeKey)) { throw Boom.badRequest(`Invalid observable type, key does not exist: ${observableTypeKey}`); } diff --git a/x-pack/platform/plugins/shared/cases/server/routes/api/get_internal_routes.ts b/x-pack/platform/plugins/shared/cases/server/routes/api/get_internal_routes.ts index 63c5953b3ea32..80abc7623a304 100644 --- a/x-pack/platform/plugins/shared/cases/server/routes/api/get_internal_routes.ts +++ b/x-pack/platform/plugins/shared/cases/server/routes/api/get_internal_routes.ts @@ -24,6 +24,7 @@ import { postObservableRoute } from './observables/post_observable'; import { similarCaseRoute } from './cases/similar'; import { patchObservableRoute } from './observables/patch_observable'; import { deleteObservableRoute } from './observables/delete_observable'; +import { findUserActionsRoute } from './internal/find_user_actions'; export const getInternalRoutes = (userProfileService: UserProfileService) => [ @@ -44,4 +45,5 @@ export const getInternalRoutes = (userProfileService: UserProfileService) => patchObservableRoute, deleteObservableRoute, similarCaseRoute, + findUserActionsRoute, ] as CaseRoute[]; diff --git a/x-pack/platform/plugins/shared/cases/server/routes/api/internal/find_user_actions.test.ts b/x-pack/platform/plugins/shared/cases/server/routes/api/internal/find_user_actions.test.ts new file mode 100644 index 0000000000000..745dfcc8eaa02 --- /dev/null +++ b/x-pack/platform/plugins/shared/cases/server/routes/api/internal/find_user_actions.test.ts @@ -0,0 +1,321 @@ +/* + * 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 { findUserActionsRoute } from './find_user_actions'; + +const userActionsMockData = { + userActions: [ + { + type: 'create_case', + payload: { + connector: { id: 'none', type: '.none', fields: null, name: 'none' }, + title: 'My Case', + tags: [], + description: 'my case desc.', + settings: { syncAlerts: false }, + owner: 'cases', + severity: 'low', + assignees: [], + status: 'open', + category: null, + customFields: [], + }, + created_at: '2025-01-07T13:31:55.427Z', + created_by: { + username: 'elastic', + full_name: null, + email: null, + profile_uid: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + }, + owner: 'cases', + action: 'create', + comment_id: null, + id: 'e11e39f5-ea29-4cbc-981b-1508cafdb0ad', + version: 'WzIsMV0=', + }, + { + payload: { comment: { comment: 'First comment', type: 'user', owner: 'cases' } }, + type: 'comment', + created_at: '2025-01-07T13:32:01.314Z', + created_by: { + username: 'elastic', + full_name: null, + email: null, + profile_uid: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + }, + owner: 'cases', + action: 'create', + comment_id: '601a03cf-71a0-4949-9407-97cf372b313b', + id: '71f67236-f2f5-4cfe-964d-a4103a9717f2', + version: 'WzUsMV0=', + }, + { + payload: { comment: { comment: 'Second comment', type: 'user', owner: 'cases' } }, + type: 'comment', + created_at: '2025-01-07T13:32:08.045Z', + created_by: { + username: 'elastic', + full_name: null, + email: null, + profile_uid: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + }, + owner: 'cases', + action: 'create', + comment_id: '2cd1eb7d-ff8a-4c0e-b904-0beb64ab166a', + id: '00414cd9-b51a-4b85-a7d3-cb39de4d61db', + version: 'WzgsMV0=', + }, + { + payload: { comment: { comment: 'Edited first comment', type: 'user', owner: 'cases' } }, + type: 'comment', + created_at: '2025-01-07T13:32:18.160Z', + created_by: { + username: 'elastic', + full_name: null, + email: null, + profile_uid: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + }, + owner: 'cases', + action: 'update', + comment_id: '123e4567-e89b-12d3-a456-426614174000', + id: '675cc9a3-5445-4aaa-ad65-21241f095546', + version: 'WzExLDFd', + }, + ], + page: 1, + perPage: 10, + total: 4, +}; + +const attachmentsMockData = { + attachments: [ + { + comment: 'Edited first comment', + type: 'user', + owner: 'cases', + created_at: '2025-01-07T13:32:01.283Z', + created_by: { + email: null, + full_name: null, + username: 'elastic', + profile_uid: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + }, + pushed_at: null, + pushed_by: null, + updated_at: '2025-01-07T13:32:18.127Z', + updated_by: { + username: 'elastic', + full_name: null, + email: null, + profile_uid: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + }, + id: '601a03cf-71a0-4949-9407-97cf372b313b', + version: 'WzksMV0=', + }, + { + comment: 'Second comment', + type: 'user', + owner: 'cases', + created_at: '2025-01-07T13:32:08.015Z', + created_by: { + email: null, + full_name: null, + username: 'elastic', + profile_uid: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + }, + pushed_at: null, + pushed_by: null, + updated_at: null, + updated_by: null, + id: '2cd1eb7d-ff8a-4c0e-b904-0beb64ab166a', + version: 'WzYsMV0=', + }, + { + comment: 'Edited first comment', + type: 'user', + owner: 'cases', + created_at: '2025-01-07T13:32:01.283Z', + created_by: { + email: null, + full_name: null, + username: 'elastic', + profile_uid: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + }, + pushed_at: null, + pushed_by: null, + updated_at: '2025-01-07T13:32:18.127Z', + updated_by: { + username: 'elastic', + full_name: null, + email: null, + profile_uid: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + }, + id: '123e4567-e89b-12d3-a456-426614174000', + version: 'WzksMV0=', + }, + ], + errors: [], +}; + +describe('findUserActionsRoute', () => { + const response = { ok: jest.fn() }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should return user actions and latest attachments', async () => { + const casesClientMock = { + userActions: { + find: jest.fn().mockResolvedValue(userActionsMockData), + }, + attachments: { + bulkGet: jest.fn().mockResolvedValue(attachmentsMockData), + }, + }; + const context = { cases: { getCasesClient: jest.fn().mockResolvedValue(casesClientMock) } }; + const request = { + params: { + case_id: 'my_fake_case_id', + }, + query: '', + }; + + // @ts-expect-error: mocking necessary properties for handler logic only, no Kibana platform + await findUserActionsRoute.handler({ context, request, response }); + + expect(casesClientMock.attachments.bulkGet).toHaveBeenCalledWith({ + attachmentIDs: [ + userActionsMockData.userActions[1].comment_id, + userActionsMockData.userActions[2].comment_id, + userActionsMockData.userActions[3].comment_id, + ], + caseID: 'my_fake_case_id', + }); + expect(response.ok).toHaveBeenCalledWith( + expect.objectContaining({ + body: expect.objectContaining({ + latestAttachments: expect.arrayContaining([ + expect.objectContaining({ + comment: 'Edited first comment', + created_at: '2025-01-07T13:32:01.283Z', + created_by: { + email: null, + full_name: null, + profile_uid: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + username: 'elastic', + }, + id: '601a03cf-71a0-4949-9407-97cf372b313b', + owner: 'cases', + pushed_at: null, + pushed_by: null, + type: 'user', + updated_at: '2025-01-07T13:32:18.127Z', + updated_by: { + email: null, + full_name: null, + profile_uid: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + username: 'elastic', + }, + version: 'WzksMV0=', + }), + ]), + }), + }) + ); + }); + + it('should return empty attachments when no commentId', async () => { + const casesClientMock = { + userActions: { + // userActionsMockData.userActions[0] must have no commentId + find: jest.fn().mockResolvedValue({ userActions: [userActionsMockData.userActions[0]] }), + }, + attachments: { + bulkGet: jest.fn().mockResolvedValue(attachmentsMockData), + }, + }; + const context = { cases: { getCasesClient: jest.fn().mockResolvedValue(casesClientMock) } }; + const request = { + params: { + case_id: 'my_fake_case_id', + }, + query: '', + }; + + // @ts-expect-error: Kibana platform types are mocked for testing, only implementing necessary properties for handler logic + await findUserActionsRoute.handler({ context, request, response }); + + expect(response.ok).toHaveBeenCalledWith( + expect.objectContaining({ + body: expect.objectContaining({ + latestAttachments: [], + }), + }) + ); + }); + + it('should filter repeated comment_ids', async () => { + userActionsMockData.userActions[1].comment_id = userActionsMockData.userActions[2].comment_id; + const casesClientMock = { + userActions: { + find: jest.fn().mockResolvedValue(userActionsMockData), + }, + attachments: { + bulkGet: jest.fn().mockResolvedValue(attachmentsMockData), + }, + }; + const context = { cases: { getCasesClient: jest.fn().mockResolvedValue(casesClientMock) } }; + const request = { + params: { + case_id: 'my_fake_case_id', + }, + query: '', + }; + + // @ts-expect-error: mocking necessary properties for handler logic only, no Kibana platform + await findUserActionsRoute.handler({ context, request, response }); + + expect(casesClientMock.attachments.bulkGet).toHaveBeenCalledWith({ + attachmentIDs: [ + userActionsMockData.userActions[1].comment_id, + userActionsMockData.userActions[3].comment_id, + ], + caseID: 'my_fake_case_id', + }); + expect(response.ok).toHaveBeenCalledWith( + expect.objectContaining({ + body: expect.objectContaining({ + latestAttachments: expect.arrayContaining([ + expect.objectContaining({ + comment: 'Edited first comment', + created_at: '2025-01-07T13:32:01.283Z', + created_by: { + email: null, + full_name: null, + profile_uid: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + username: 'elastic', + }, + id: '601a03cf-71a0-4949-9407-97cf372b313b', + owner: 'cases', + pushed_at: null, + pushed_by: null, + type: 'user', + updated_at: '2025-01-07T13:32:18.127Z', + updated_by: { + email: null, + full_name: null, + profile_uid: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + username: 'elastic', + }, + version: 'WzksMV0=', + }), + ]), + }), + }) + ); + }); +}); diff --git a/x-pack/platform/plugins/shared/cases/server/routes/api/internal/find_user_actions.ts b/x-pack/platform/plugins/shared/cases/server/routes/api/internal/find_user_actions.ts new file mode 100644 index 0000000000000..9ad00346a565c --- /dev/null +++ b/x-pack/platform/plugins/shared/cases/server/routes/api/internal/find_user_actions.ts @@ -0,0 +1,79 @@ +/* + * 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 { schema } from '@kbn/config-schema'; + +import { isCommentUserAction } from '../../../../common/utils/user_actions'; +import type { attachmentApiV1, userActionApiV1 } from '../../../../common/types/api'; +import { INTERNAL_CASE_FIND_USER_ACTIONS_URL } from '../../../../common/constants'; +import { createCaseError } from '../../../common/error'; +import { createCasesRoute } from '../create_cases_route'; + +const params = { + params: schema.object({ + case_id: schema.string(), + }), +}; + +export const findUserActionsRoute = createCasesRoute({ + method: 'get', + path: INTERNAL_CASE_FIND_USER_ACTIONS_URL, + params, + routerOptions: { + access: 'public', + summary: 'Get user actions by case', + tags: ['oas-tag:cases'], + }, + handler: async ({ context, request, response }) => { + try { + const caseContext = await context.cases; + const casesClient = await caseContext.getCasesClient(); + const caseId = request.params.case_id; + const options = request.query as userActionApiV1.UserActionFindRequest; + + const userActionsResponse: userActionApiV1.UserActionFindResponse = + await casesClient.userActions.find({ + caseId, + params: options, + }); + + const uniqueCommentIds: Set = new Set(); + for (const action of userActionsResponse.userActions) { + if (isCommentUserAction(action) && action.comment_id) { + uniqueCommentIds.add(action.comment_id); + } + } + const commentIds = Array.from(uniqueCommentIds); + + let attachmentRes: attachmentApiV1.BulkGetAttachmentsResponse = { + attachments: [], + errors: [], + }; + + if (commentIds.length > 0) { + attachmentRes = await casesClient.attachments.bulkGet({ + caseID: caseId, + attachmentIDs: commentIds, + }); + } + + const res: userActionApiV1.UserActionInternalFindResponse = { + ...userActionsResponse, + latestAttachments: attachmentRes.attachments, + }; + + return response.ok({ + body: res, + }); + } catch (error) { + throw createCaseError({ + message: `Failed to retrieve case details in route case id: ${request.params.case_id}: \n${error}`, + error, + }); + } + }, +}); diff --git a/x-pack/platform/plugins/shared/cases/server/services/attachments/index.ts b/x-pack/platform/plugins/shared/cases/server/services/attachments/index.ts index 165949b0e37d8..47091a867e7b0 100644 --- a/x-pack/platform/plugins/shared/cases/server/services/attachments/index.ts +++ b/x-pack/platform/plugins/shared/cases/server/services/attachments/index.ts @@ -13,7 +13,7 @@ import type { SavedObjectsUpdateResponse, } from '@kbn/core/server'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { fromKueryExpression } from '@kbn/es-query'; import { AttachmentAttributesRt, AttachmentType } from '../../../common/types/domain'; import { decodeOrThrow } from '../../common/runtime_types'; diff --git a/x-pack/platform/plugins/shared/cases/server/services/attachments/operations/get.ts b/x-pack/platform/plugins/shared/cases/server/services/attachments/operations/get.ts index da258afc5eeb9..7b3125ba02005 100644 --- a/x-pack/platform/plugins/shared/cases/server/services/attachments/operations/get.ts +++ b/x-pack/platform/plugins/shared/cases/server/services/attachments/operations/get.ts @@ -10,7 +10,7 @@ import type { SavedObjectsBulkResponse, SavedObjectsFindResponse, } from '@kbn/core/server'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { FILE_SO_TYPE } from '@kbn/files-plugin/common'; import { isSOError } from '../../../common/error'; import { decodeOrThrow } from '../../../common/runtime_types'; diff --git a/x-pack/platform/plugins/shared/cases/server/services/attachments/types.ts b/x-pack/platform/plugins/shared/cases/server/services/attachments/types.ts index c9c5de01e3a4a..3293410793b05 100644 --- a/x-pack/platform/plugins/shared/cases/server/services/attachments/types.ts +++ b/x-pack/platform/plugins/shared/cases/server/services/attachments/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import type { Logger, SavedObject, diff --git a/x-pack/platform/plugins/shared/cases/server/services/cases/index.ts b/x-pack/platform/plugins/shared/cases/server/services/cases/index.ts index 034e369b1c700..55e82e35eb13c 100644 --- a/x-pack/platform/plugins/shared/cases/server/services/cases/index.ts +++ b/x-pack/platform/plugins/shared/cases/server/services/cases/index.ts @@ -18,7 +18,7 @@ import type { SavedObjectsBulkDeleteOptions, } from '@kbn/core/server'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { nodeBuilder } from '@kbn/es-query'; import type { Case, CaseStatuses, User } from '../../../common/types/domain'; diff --git a/x-pack/platform/plugins/shared/cases/server/services/user_actions/index.ts b/x-pack/platform/plugins/shared/cases/server/services/user_actions/index.ts index 911f31c5c52f2..deb8bd640dbf1 100644 --- a/x-pack/platform/plugins/shared/cases/server/services/user_actions/index.ts +++ b/x-pack/platform/plugins/shared/cases/server/services/user_actions/index.ts @@ -11,7 +11,7 @@ import type { SavedObjectsRawDoc, } from '@kbn/core/server'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import type { KueryNode } from '@kbn/es-query'; import type { CaseUserActionDeprecatedResponse } from '../../../common/types/api'; import { UserActionTypes } from '../../../common/types/domain'; diff --git a/x-pack/platform/plugins/shared/entity_manager/common/constants_entities.ts b/x-pack/platform/plugins/shared/entity_manager/common/constants_entities.ts index c17e6f33918c6..8eac9dc91edda 100644 --- a/x-pack/platform/plugins/shared/entity_manager/common/constants_entities.ts +++ b/x-pack/platform/plugins/shared/entity_manager/common/constants_entities.ts @@ -20,6 +20,8 @@ export const ENTITY_ENTITY_COMPONENT_TEMPLATE_V1 = export const ENTITY_EVENT_COMPONENT_TEMPLATE_V1 = `${ENTITY_BASE_PREFIX}_${ENTITY_SCHEMA_VERSION_V1}_event` as const; +export const ECS_MAPPINGS_COMPONENT_TEMPLATE = 'ecs@mappings' as const; + // History constants export const ENTITY_HISTORY_BASE_COMPONENT_TEMPLATE_V1 = `${ENTITY_BASE_PREFIX}_${ENTITY_SCHEMA_VERSION_V1}_${ENTITY_HISTORY}_base` as const; diff --git a/x-pack/platform/plugins/shared/entity_manager/server/lib/entities/templates/__snapshots__/entities_latest_template.test.ts.snap b/x-pack/platform/plugins/shared/entity_manager/server/lib/entities/templates/__snapshots__/entities_latest_template.test.ts.snap index 9653c5fda96c6..f60081dfb1ff4 100644 --- a/x-pack/platform/plugins/shared/entity_manager/server/lib/entities/templates/__snapshots__/entities_latest_template.test.ts.snap +++ b/x-pack/platform/plugins/shared/entity_manager/server/lib/entities/templates/__snapshots__/entities_latest_template.test.ts.snap @@ -9,6 +9,7 @@ Object { "managed_by": "elastic_entity_model", }, "composed_of": Array [ + "ecs@mappings", "entities_v1_latest_base", "entities_v1_entity", "entities_v1_event", @@ -80,6 +81,7 @@ Object { "managed_by": "elastic_entity_model", }, "composed_of": Array [ + "ecs@mappings", "entities_v1_latest_base", "entities_v1_entity", "entities_v1_event", diff --git a/x-pack/platform/plugins/shared/entity_manager/server/lib/entities/templates/entities_latest_template.ts b/x-pack/platform/plugins/shared/entity_manager/server/lib/entities/templates/entities_latest_template.ts index e0c02c7471217..3781d51a822dc 100644 --- a/x-pack/platform/plugins/shared/entity_manager/server/lib/entities/templates/entities_latest_template.ts +++ b/x-pack/platform/plugins/shared/entity_manager/server/lib/entities/templates/entities_latest_template.ts @@ -15,6 +15,7 @@ import { } from '@kbn/entities-schema'; import { generateLatestIndexTemplateId } from '../helpers/generate_component_id'; import { + ECS_MAPPINGS_COMPONENT_TEMPLATE, ENTITY_ENTITY_COMPONENT_TEMPLATE_V1, ENTITY_EVENT_COMPONENT_TEMPLATE_V1, ENTITY_LATEST_BASE_COMPONENT_TEMPLATE_V1, @@ -34,6 +35,7 @@ export const generateEntitiesLatestIndexTemplateConfig = ( }, ignore_missing_component_templates: getCustomLatestTemplateComponents(definition), composed_of: [ + ECS_MAPPINGS_COMPONENT_TEMPLATE, ENTITY_LATEST_BASE_COMPONENT_TEMPLATE_V1, ENTITY_ENTITY_COMPONENT_TEMPLATE_V1, ENTITY_EVENT_COMPONENT_TEMPLATE_V1, diff --git a/x-pack/platform/plugins/shared/event_log/server/es/cluster_client_adapter.ts b/x-pack/platform/plugins/shared/event_log/server/es/cluster_client_adapter.ts index 1eb0f482e1d0b..e366870c22858 100644 --- a/x-pack/platform/plugins/shared/event_log/server/es/cluster_client_adapter.ts +++ b/x-pack/platform/plugins/shared/event_log/server/es/cluster_client_adapter.ts @@ -11,7 +11,7 @@ import { reject, isUndefined, isNumber, pick, isEmpty, get } from 'lodash'; import type { PublicMethodsOf } from '@kbn/utility-types'; import { Logger, ElasticsearchClient } from '@kbn/core/server'; import util from 'util'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { fromKueryExpression, toElasticsearchQuery, KueryNode, nodeBuilder } from '@kbn/es-query'; import { IEvent, IValidatedEvent, SAVED_OBJECT_REL_PRIMARY } from '../types'; import { AggregateOptionsType, FindOptionsType, QueryOptionsType } from '../event_log_client'; @@ -399,7 +399,7 @@ export class ClusterClientAdapter { reset(): void; } -export class HashedCache { +export class HashedCache { private cache: LRUCache; constructor(options: LRUCache.Options = { max: 500 }) { diff --git a/x-pack/platform/plugins/shared/fleet/README.md b/x-pack/platform/plugins/shared/fleet/README.md index f20d22625e776..94a28952885d4 100644 --- a/x-pack/platform/plugins/shared/fleet/README.md +++ b/x-pack/platform/plugins/shared/fleet/README.md @@ -130,13 +130,18 @@ Note: if you need to do simultaneous Kibana and Fleet Server development, refer Kibana primarily uses Jest for unit testing. Each plugin or package defines a `jest.config.js` that extends a preset provided by the `@kbn/test` package. Unless you intend to run all unit tests within the project, you should provide the Jest configuration for Fleet. The following command runs all Fleet unit tests: ```sh -yarn jest --config x-pack/platform/plugins/shared/fleet/jest.config.js +yarn jest --config x-pack/platform/plugins/shared/fleet/jest.config.dev.js ``` You can also run a specific test by passing the filepath as an argument, e.g.: ```sh -yarn jest --config x-pack/platform/plugins/shared/fleet/jest.config.js x-pack/platform/plugins/shared/fleet/common/services/validate_package_policy.test.ts +yarn jest --config x-pack/platform/plugins/shared/fleet/jest.config.dev.js x-pack/platform/plugins/shared/fleet/common/services/validate_package_policy.test.ts +``` + +Or alternatively: +```sh +yarn test:jest x-pack/platform/plugins/shared/fleet/common/services/validate_package_policy.test.ts ``` #### API integration tests (stateful) diff --git a/x-pack/platform/plugins/shared/fleet/common/authz.test.ts b/x-pack/platform/plugins/shared/fleet/common/authz.test.ts index 28a01e72992b6..abe2b8c8d22d2 100644 --- a/x-pack/platform/plugins/shared/fleet/common/authz.test.ts +++ b/x-pack/platform/plugins/shared/fleet/common/authz.test.ts @@ -69,7 +69,7 @@ describe('fleet authz', () => { navLinks: {}, management: {}, catalogue: {}, - siem: endpointCapabilities, + siemV2: endpointCapabilities, transform: transformCapabilities, }); @@ -95,7 +95,7 @@ describe('fleet authz', () => { navLinks: {}, management: {}, catalogue: {}, - siem: endpointExceptionsCapabilities, + siemV2: endpointExceptionsCapabilities, }); expect(actual).toEqual(expected); @@ -120,7 +120,7 @@ describe('fleet authz', () => { navLinks: {}, management: {}, catalogue: {}, - siem: endpointCapabilities, + siemV2: endpointCapabilities, }); expect(actual).toEqual(expected); diff --git a/x-pack/platform/plugins/shared/fleet/common/authz.ts b/x-pack/platform/plugins/shared/fleet/common/authz.ts index 409c5eac01d65..d93d4338a107f 100644 --- a/x-pack/platform/plugins/shared/fleet/common/authz.ts +++ b/x-pack/platform/plugins/shared/fleet/common/authz.ts @@ -178,7 +178,7 @@ export function calculatePackagePrivilegesFromCapabilities( (acc, [privilege, { privilegeName }]) => { acc[privilege] = { executePackageAction: - (capabilities.siem && (capabilities.siem[privilegeName] as boolean)) || false, + (capabilities.siemV2 && (capabilities.siemV2[privilegeName] as boolean)) || false, }; return acc; }, @@ -208,14 +208,14 @@ export function calculatePackagePrivilegesFromCapabilities( export function calculateEndpointExceptionsPrivilegesFromCapabilities( capabilities: Capabilities | undefined ): FleetAuthz['endpointExceptionsPrivileges'] { - if (!capabilities || !capabilities.siem) { + if (!capabilities || !capabilities.siemV2) { return; } const endpointExceptionsActions = Object.keys(ENDPOINT_EXCEPTIONS_PRIVILEGES).reduce< Record >((acc, privilegeName) => { - acc[privilegeName] = (capabilities.siem[privilegeName] as boolean) || false; + acc[privilegeName] = (capabilities.siemV2[privilegeName] as boolean) || false; return acc; }, {}); diff --git a/x-pack/platform/plugins/shared/fleet/common/constants/authz.ts b/x-pack/platform/plugins/shared/fleet/common/constants/authz.ts index 8cfa1d8f854ea..81928bfeb5060 100644 --- a/x-pack/platform/plugins/shared/fleet/common/constants/authz.ts +++ b/x-pack/platform/plugins/shared/fleet/common/constants/authz.ts @@ -8,7 +8,7 @@ import { deepFreeze } from '@kbn/std'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; -const SECURITY_SOLUTION_APP_ID = 'siem'; +const SECURITY_SOLUTION_APP_ID = 'siemV2'; export interface PrivilegeMapObject { appId: string; diff --git a/x-pack/platform/plugins/shared/fleet/common/services/agent_utils.ts b/x-pack/platform/plugins/shared/fleet/common/services/agent_utils.ts index c0e935543fc39..b2622aa6df9ac 100644 --- a/x-pack/platform/plugins/shared/fleet/common/services/agent_utils.ts +++ b/x-pack/platform/plugins/shared/fleet/common/services/agent_utils.ts @@ -4,6 +4,9 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import semverValid from 'semver/functions/valid'; + +import type { AgentTargetVersion } from '../types'; export function removeSOAttributes(kuery: string): string { return kuery.replace(/attributes\./g, '').replace(/fleet-agents\./g, ''); @@ -20,3 +23,25 @@ export function getSortConfig( : []; return [{ [sortField]: { order: sortOrder } }, ...secondarySort]; } + +export function checkTargetVersionsValidity( + requiredVersions: AgentTargetVersion[] +): string | undefined { + const versions = requiredVersions.map((v) => v.version); + const uniqueVersions = new Set(versions); + if (versions.length !== uniqueVersions.size) { + return `duplicate versions not allowed`; + } + if (requiredVersions.some((item) => !item.percentage)) { + return `percentage is required`; + } + for (const version of versions) { + if (!semverValid(version)) { + return `invalid semver version ${version}`; + } + } + const sumOfPercentages = requiredVersions.reduce((acc, v) => acc + v.percentage, 0); + if (sumOfPercentages > 100) { + return `sum of percentages cannot exceed 100`; + } +} diff --git a/x-pack/platform/plugins/shared/fleet/common/services/index.ts b/x-pack/platform/plugins/shared/fleet/common/services/index.ts index 7061d6d3028d8..ce82633174fb3 100644 --- a/x-pack/platform/plugins/shared/fleet/common/services/index.ts +++ b/x-pack/platform/plugins/shared/fleet/common/services/index.ts @@ -92,4 +92,4 @@ export { isAgentVersionLessThanFleetServer, } from './check_fleet_server_versions'; -export { removeSOAttributes, getSortConfig } from './agent_utils'; +export { removeSOAttributes, getSortConfig, checkTargetVersionsValidity } from './agent_utils'; diff --git a/x-pack/platform/plugins/shared/fleet/common/types/models/agent_policy.ts b/x-pack/platform/plugins/shared/fleet/common/types/models/agent_policy.ts index 3cc7716ca074a..26244c1e486a8 100644 --- a/x-pack/platform/plugins/shared/fleet/common/types/models/agent_policy.ts +++ b/x-pack/platform/plugins/shared/fleet/common/types/models/agent_policy.ts @@ -44,6 +44,7 @@ export interface NewAgentPolicy { keep_monitoring_alive?: boolean | null; supports_agentless?: boolean | null; global_data_tags?: GlobalDataTag[]; + agentless?: AgentlessPolicy; monitoring_pprof_enabled?: boolean; monitoring_http?: { enabled?: boolean; @@ -72,6 +73,15 @@ export interface AgentTargetVersion { percentage: number; } +export interface AgentlessPolicy { + resources?: { + requests?: { + memory?: string; + cpu?: string; + }; + }; +} + export interface GlobalDataTag { name: string; value: string | number; diff --git a/x-pack/platform/plugins/shared/fleet/common/types/models/epm.ts b/x-pack/platform/plugins/shared/fleet/common/types/models/epm.ts index af8a0acf9b2d4..8d2dda41f727f 100644 --- a/x-pack/platform/plugins/shared/fleet/common/types/models/epm.ts +++ b/x-pack/platform/plugins/shared/fleet/common/types/models/epm.ts @@ -201,6 +201,12 @@ export interface DeploymentsModesAgentless extends DeploymentsModesDefault { organization?: string; division?: string; team?: string; + resources?: { + requests: { + cpu: string; + memory: string; + }; + }; } export interface DeploymentsModes { agentless: DeploymentsModesAgentless; diff --git a/x-pack/platform/plugins/shared/fleet/cypress/e2e/agent_policy.cy.ts b/x-pack/platform/plugins/shared/fleet/cypress/e2e/agent_policy.cy.ts index 9c0f9ef134b56..6422f3307e93d 100644 --- a/x-pack/platform/plugins/shared/fleet/cypress/e2e/agent_policy.cy.ts +++ b/x-pack/platform/plugins/shared/fleet/cypress/e2e/agent_policy.cy.ts @@ -7,6 +7,7 @@ import { setupFleetServer } from '../tasks/fleet_server'; import { AGENT_FLYOUT, AGENT_POLICY_DETAILS_PAGE } from '../screens/fleet'; import { login } from '../tasks/login'; +import { visit } from '../tasks/common'; describe('Edit agent policy', () => { beforeEach(() => { @@ -37,7 +38,7 @@ describe('Edit agent policy', () => { }); it('should edit agent policy', () => { - cy.visit('/app/fleet/policies/policy-1/settings'); + visit('/app/fleet/policies/policy-1/settings'); cy.get('[placeholder="Optional description"').clear().type('desc'); cy.intercept('/api/fleet/agent_policies/policy-1', { @@ -135,7 +136,7 @@ describe('Edit agent policy', () => { }, }); - cy.visit('/app/fleet/policies/policy-1'); + visit('/app/fleet/policies/policy-1'); cy.getBySel(AGENT_POLICY_DETAILS_PAGE.ADD_AGENT_LINK).click(); cy.getBySel(AGENT_FLYOUT.KUBERNETES_PLATFORM_TYPE).click(); diff --git a/x-pack/platform/plugins/shared/fleet/cypress/tasks/common.ts b/x-pack/platform/plugins/shared/fleet/cypress/tasks/common.ts index 2bf201b11a498..6fead86fe952f 100644 --- a/x-pack/platform/plugins/shared/fleet/cypress/tasks/common.ts +++ b/x-pack/platform/plugins/shared/fleet/cypress/tasks/common.ts @@ -80,6 +80,10 @@ const disableNewFeaturesTours = (window: Window) => { }); }; +const disableFleetTours = (window: Window) => { + window.localStorage.setItem('fleet.autoUpgradeAgentsTour', JSON.stringify({ active: false })); +}; + export const waitForPageToBeLoaded = () => { cy.get(LOADING_INDICATOR_HIDDEN).should('exist'); cy.get(LOADING_INDICATOR).should('not.exist'); @@ -115,6 +119,7 @@ export const visit = (url: string, options: Partial = {}, options.onBeforeLoad?.(win); disableNewFeaturesTours(win); + disableFleetTours(win); }, onLoad: (win) => { options.onLoad?.(win); diff --git a/x-pack/platform/plugins/shared/fleet/cypress/tasks/navigation.ts b/x-pack/platform/plugins/shared/fleet/cypress/tasks/navigation.ts index 741a2cf761e8c..71edf361b351e 100644 --- a/x-pack/platform/plugins/shared/fleet/cypress/tasks/navigation.ts +++ b/x-pack/platform/plugins/shared/fleet/cypress/tasks/navigation.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { visit } from './common'; + export const INTEGRATIONS = 'app/integrations#/'; export const FLEET = 'app/fleet/'; export const LOGIN_API_ENDPOINT = '/internal/security/login'; @@ -16,5 +18,5 @@ export const hostDetailsUrl = (hostName: string) => `/app/security/hosts/${hostName}/authentications`; export const navigateTo = (page: string) => { - cy.visit(page); + visit(page); }; diff --git a/x-pack/platform/plugins/shared/fleet/jest.config.dev.js b/x-pack/platform/plugins/shared/fleet/jest.config.dev.js index ff985be3a5d6e..80f972de854be 100644 --- a/x-pack/platform/plugins/shared/fleet/jest.config.dev.js +++ b/x-pack/platform/plugins/shared/fleet/jest.config.dev.js @@ -6,12 +6,12 @@ */ module.exports = { - preset: '@kbn/test/jest', + preset: '@kbn/test', rootDir: '../../../../..', roots: ['/x-pack/platform/plugins/shared/fleet'], projects: [ - '/x-pack/platform/plugins/shared/fleet/common/*/jest.config.js', - '/x-pack/platform/plugins/shared/fleet/server/*/jest.config.js', - '/x-pack/platform/plugins/shared/fleet/public/*/jest.config.js', + '/x-pack/platform/plugins/shared/fleet/common/jest.config.js', + '/x-pack/platform/plugins/shared/fleet/server/jest.config.js', + '/x-pack/platform/plugins/shared/fleet/public/jest.config.js', ], }; diff --git a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/layouts/default/default.tsx b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/layouts/default/default.tsx index b6cac5e88c36e..4798318c9d971 100644 --- a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/layouts/default/default.tsx +++ b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/layouts/default/default.tsx @@ -14,6 +14,8 @@ import type { Section } from '../../sections'; import { useLink, useConfig, useAuthz, useStartServices } from '../../hooks'; import { WithHeaderLayout } from '../../../../layouts'; +import { AutoUpgradeAgentsTour } from '../../sections/agent_policy/components/auto_upgrade_agents_tour'; + import { DefaultPageTitle } from './default_page_title'; interface Props { @@ -56,6 +58,7 @@ export const DefaultLayout: React.FunctionComponent = ({ isSelected: section === 'agent_policies', href: getHref('policies_list'), 'data-test-subj': 'fleet-agent-policies-tab', + id: 'fleet-agent-policies-tab', }, { name: ( @@ -141,6 +144,7 @@ export const DefaultLayout: React.FunctionComponent = ({ } rightColumn={rightColumn} tabs={tabs}> {children} + ); }; diff --git a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/components/actions_menu.tsx b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/components/actions_menu.tsx index 961170976194f..166c63bbcf128 100644 --- a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/components/actions_menu.tsx +++ b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/components/actions_menu.tsx @@ -10,7 +10,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { EuiContextMenuItem, EuiPortal } from '@elastic/eui'; import type { AgentPolicy } from '../../../types'; -import { useAuthz } from '../../../hooks'; +import { useAgentPolicyRefresh, useAuthz } from '../../../hooks'; import { AgentEnrollmentFlyout, ContextMenuActions, @@ -22,6 +22,8 @@ import { policyHasFleetServer } from '../../../services'; import { AgentUpgradeAgentModal } from '../../agents/components'; +import { ManageAutoUpgradeAgentsModal } from '../../agents/components/manage_auto_upgrade_agents_modal'; + import { AgentPolicyYamlFlyout } from './agent_policy_yaml_flyout'; import { AgentPolicyCopyProvider } from './agent_policy_copy_provider'; import { AgentPolicyDeleteProvider } from './agent_policy_delete_provider'; @@ -49,6 +51,9 @@ export const AgentPolicyActionMenu = memo<{ const [isUninstallCommandFlyoutOpen, setIsUninstallCommandFlyoutOpen] = useState(false); const [isUpgradeAgentsModalOpen, setIsUpgradeAgentsModalOpen] = useState(false); + const [isManageAutoUpgradeAgentsModalOpen, setIsManageAutoUpgradeAgentsModalOpen] = + useState(false); + const refreshAgentPolicy = useAgentPolicyRefresh(); const isFleetServerPolicy = useMemo( () => @@ -98,6 +103,23 @@ export const AgentPolicyActionMenu = memo<{ ); + const manageAutoUpgradeAgentsItem = ( + { + setIsContextMenuOpen(false); + setIsManageAutoUpgradeAgentsModalOpen(!isManageAutoUpgradeAgentsModalOpen); + }} + key="manageAutoUpgradeAgents" + > + + + ); + const deletePolicyItem = ( , viewPolicyItem, + manageAutoUpgradeAgentsItem, copyPolicyItem, deletePolicyItem, ]; @@ -215,6 +238,7 @@ export const AgentPolicyActionMenu = memo<{ }} key="upgradeAgents" data-test-subj="agentPolicyActionMenuUpgradeAgentsButton" + disabled={(agentPolicy.agents || 0) === 0} > )} + {isManageAutoUpgradeAgentsModalOpen && ( + + { + setIsManageAutoUpgradeAgentsModalOpen(false); + if (refreshPolicy) { + refreshAgentPolicy(); + } + }} + /> + + )} {isUninstallCommandFlyoutOpen && ( = ({ anchor }) => { + const { storage, uiSettings } = useStartServices(); + + const [tourState, setTourState] = useState({ isOpen: true }); + + const isTourHidden = + uiSettings.get('hideAnnouncements', false) || + ( + storage.get(TOUR_STORAGE_KEYS.AUTO_UPGRADE_AGENTS) as + | TOUR_STORAGE_CONFIG['AUTO_UPGRADE_AGENTS'] + | undefined + )?.active === false; + + const setTourAsHidden = () => { + storage.set(TOUR_STORAGE_KEYS.AUTO_UPGRADE_AGENTS, { + active: false, + } as TOUR_STORAGE_CONFIG['AUTO_UPGRADE_AGENTS']); + }; + + const onFinish = () => { + setTourState({ isOpen: false }); + setTourAsHidden(); + }; + + return ( + <> + + + + } + isStepOpen={!isTourHidden && tourState.isOpen} + onFinish={onFinish} + minWidth={360} + maxWidth={360} + step={1} + stepsTotal={1} + title={ + + } + anchorPosition="downLeft" + anchor={anchor} + /> + + ); +}; diff --git a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts index 613418cda5ea9..2f6d87e5c1db7 100644 --- a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts +++ b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts @@ -125,6 +125,24 @@ describe('useSetupTechnology', () => { inactivity_timeout: 3600, }; + const packageInfoWithoutAgentless = { + policy_templates: [ + { + name: 'cspm', + title: 'Template 1', + description: '', + deployment_modes: { + default: { + enabled: true, + }, + agentless: { + enabled: false, + }, + }, + }, + ] as RegistryPolicyTemplate[], + } as PackageInfo; + const packageInfoMock = { policy_templates: [ { @@ -140,6 +158,40 @@ describe('useSetupTechnology', () => { organization: 'org', division: 'div', team: 'team', + resources: { + requests: { + memory: '256Mi', + cpu: '100m', + }, + }, + }, + }, + }, + { + name: 'not-cspm', + title: 'Template 2', + description: '', + deployment_modes: { + default: { + enabled: true, + }, + }, + }, + ] as RegistryPolicyTemplate[], + } as PackageInfo; + + const packageInfoWithoutResources = { + policy_templates: [ + { + name: 'cspm', + title: 'Template 1', + description: '', + deployment_modes: { + default: { + enabled: true, + }, + agentless: { + enabled: true, }, }, }, @@ -473,6 +525,14 @@ describe('useSetupTechnology', () => { { name: 'division', value: 'div' }, { name: 'team', value: 'team' }, ], + agentless: { + resources: { + requests: { + memory: '256Mi', + cpu: '100m', + }, + }, + }, }); expect(updatePackagePolicyMock).toHaveBeenCalledWith({ supports_agentless: true }); }); @@ -488,6 +548,133 @@ describe('useSetupTechnology', () => { }); }); + it('should have agentless resources section on the request when creating agentless policy with resources', async () => { + (useConfig as MockFn).mockReturnValue({ + agentless: { + enabled: true, + api: { + url: 'https://agentless.api.url', + }, + }, + } as any); + (useStartServices as MockFn).mockReturnValue({ + cloud: { + isCloudEnabled: true, + }, + }); + + const { result } = renderHook(() => + useSetupTechnology({ + setNewAgentPolicy, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicies: updateAgentPoliciesMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + packagePolicy: packagePolicyMock, + packageInfo: packageInfoMock, + updatePackagePolicy: updatePackagePolicyMock, + }) + ); + + act(() => { + result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS); + }); + + await waitFor(() => { + expect(setNewAgentPolicy).toHaveBeenCalledWith( + expect.objectContaining({ + agentless: { + resources: { + requests: { + memory: '256Mi', + cpu: '100m', + }, + }, + }, + }) + ); + }); + }); + + it('should not have agentless section on the request when creating agentless policy without resources', async () => { + (useConfig as MockFn).mockReturnValue({ + agentless: { + enabled: true, + api: { + url: 'https://agentless.api.url', + }, + }, + } as any); + (useStartServices as MockFn).mockReturnValue({ + cloud: { + isCloudEnabled: true, + }, + }); + + const { result } = renderHook(() => + useSetupTechnology({ + setNewAgentPolicy, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicies: updateAgentPoliciesMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + packagePolicy: packagePolicyMock, + packageInfo: packageInfoWithoutResources, + updatePackagePolicy: updatePackagePolicyMock, + }) + ); + + act(() => { + result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS); + }); + + await waitFor(() => { + expect(setNewAgentPolicy).toHaveBeenCalledWith( + expect.not.objectContaining({ + agentless: {}, + }) + ); + }); + }); + + it('should not have agentless section on the request when creating policy with agentless disabled', async () => { + (useConfig as MockFn).mockReturnValue({ + agentless: { + enabled: true, + api: { + url: 'https://agentless.api.url', + }, + }, + } as any); + (useStartServices as MockFn).mockReturnValue({ + cloud: { + isCloudEnabled: true, + }, + }); + + const { result } = renderHook(() => + useSetupTechnology({ + setNewAgentPolicy, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicies: updateAgentPoliciesMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + packagePolicy: packagePolicyMock, + packageInfo: packageInfoWithoutAgentless, + updatePackagePolicy: updatePackagePolicyMock, + }) + ); + + act(() => { + result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS); + }); + + await waitFor(() => { + expect(setNewAgentPolicy).toHaveBeenCalledWith( + expect.not.objectContaining({ + agentless: {}, + }) + ); + }); + }); + it('should have global_data_tags with the integration team when creating agentless policy with global_data_tags', async () => { (useConfig as MockFn).mockReturnValue({ agentless: { diff --git a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts index fe5e5ca0e03f2..b8ae5c77d5815 100644 --- a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts +++ b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts @@ -131,6 +131,12 @@ export function useSetupTechnology({ name: agentlessPolicyName, global_data_tags: getGlobaDataTags(packageInfo), }; + + const agentlessPolicy = getAgentlessPolicy(packageInfo); + if (agentlessPolicy) { + nextNewAgentlessPolicy.agentless = agentlessPolicy; + } + setCurrentAgentPolicy(nextNewAgentlessPolicy); setNewAgentPolicy(nextNewAgentlessPolicy as NewAgentPolicy); updateAgentPolicies([nextNewAgentlessPolicy] as AgentPolicy[]); @@ -206,3 +212,26 @@ const getGlobaDataTags = (packageInfo?: PackageInfo) => { }, ]; }; + +const getAgentlessPolicy = (packageInfo?: PackageInfo) => { + if ( + !packageInfo?.policy_templates && + !packageInfo?.policy_templates?.some((policy) => policy.deployment_modes) + ) { + return; + } + const agentlessPolicyTemplate = packageInfo.policy_templates.find( + (policy) => policy.deployment_modes + ); + + // assumes that all the policy templates agentless deployments modes indentify have the same organization, division and team + const agentlessInfo = agentlessPolicyTemplate?.deployment_modes?.agentless; + + if (!agentlessInfo?.resources) { + return; + } + + return { + resources: agentlessInfo.resources, + }; +}; diff --git a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/details_page/components/header/right_content.tsx b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/details_page/components/header/right_content.tsx index 6603698a80186..47d78462dc288 100644 --- a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/details_page/components/header/right_content.tsx +++ b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/details_page/components/header/right_content.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useMemo } from 'react'; +import React, { useMemo, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedDate, FormattedMessage } from '@kbn/i18n-react'; import styled from 'styled-components'; @@ -20,14 +20,18 @@ import { EuiLink, EuiToolTip, EuiIconTip, + EuiPortal, + EuiNotificationBadge, } from '@elastic/eui'; -import { useAuthz, useLink } from '../../../../../hooks'; +import { useAgentPolicyRefresh, useAuthz, useLink } from '../../../../../hooks'; import type { AgentPolicy } from '../../../../../types'; import { AgentPolicyActionMenu, LinkedAgentCount } from '../../../components'; import { AddAgentHelpPopover } from '../../../../../components'; import { FLEET_SERVER_PACKAGE } from '../../../../../../../../common/constants'; import { getRootIntegrations } from '../../../../../../../../common/services'; +import { ManageAutoUpgradeAgentsModal } from '../../../../agents/components/manage_auto_upgrade_agents_modal'; +import { AutoUpgradeAgentsTour } from '../../../components/auto_upgrade_agents_tour'; export interface HeaderRightContentProps { isLoading: boolean; @@ -55,6 +59,9 @@ export const HeaderRightContent: React.FunctionComponent(false); + const refreshAgentPolicy = useAgentPolicyRefresh(); const isFleetServerPolicy = useMemo( () => @@ -84,154 +91,215 @@ export const HeaderRightContent: React.FunctionComponent - {isLoading || !agentPolicy - ? null - : [ - { - label: i18n.translate('xpack.fleet.policyDetails.summary.revision', { - defaultMessage: 'Revision', - }), - content: agentPolicy.revision ?? 0, - }, - { isDivider: true }, - { - label: i18n.translate('xpack.fleet.policyDetails.summary.integrations', { - defaultMessage: 'Integrations', - }), - content: ( - - ), - }, - { isDivider: true }, - ...(authz.fleet.readAgents && !agentPolicy?.supports_agentless - ? [ - { - label: i18n.translate('xpack.fleet.policyDetails.summary.usedBy', { - defaultMessage: 'Agents', - }), - content: - !agentPolicy.agents && isFleetServerPolicy && authz.fleet.addFleetServers ? ( - { - setIsAddAgentHelpPopoverOpen(false); - }} - /> - ) : !agentPolicy.agents && !isFleetServerPolicy && authz.fleet.addAgents ? ( - { - setIsAddAgentHelpPopoverOpen(false); - }} - /> - ) : ( - + <> + + {isLoading || !agentPolicy + ? null + : [ + { + label: i18n.translate('xpack.fleet.policyDetails.summary.revision', { + defaultMessage: 'Revision', + }), + content: agentPolicy.revision ?? 0, + }, + { isDivider: true }, + { + label: i18n.translate('xpack.fleet.policyDetails.summary.integrations', { + defaultMessage: 'Integrations', + }), + content: ( + + ), + }, + { isDivider: true }, + ...(authz.fleet.readAgents && !agentPolicy?.supports_agentless + ? [ + { + label: i18n.translate('xpack.fleet.policyDetails.summary.usedBy', { + defaultMessage: 'Agents', + }), + content: + !agentPolicy.agents && + isFleetServerPolicy && + authz.fleet.addFleetServers ? ( + { + setIsAddAgentHelpPopoverOpen(false); + }} + /> + ) : !agentPolicy.agents && !isFleetServerPolicy && authz.fleet.addAgents ? ( + { + setIsAddAgentHelpPopoverOpen(false); + }} + /> + ) : ( + + + + + + + + + + + } + > + + + + {getRootIntegrations(agentPolicy.package_policies || []).length > 0 && + (agentPolicy.unprivileged_agents || 0) > 0 && ( + + + } + /> + + )} + + ), + }, + { isDivider: true }, + ] + : []), + { + label: i18n.translate('xpack.fleet.policyDetails.summary.lastUpdated', { + defaultMessage: 'Last updated on', + }), + content: + (agentPolicy && ( + + )) || + '', + }, + { isDivider: true }, + ...(authz.fleet.allAgentPolicies + ? [ + { + label: i18n.translate('xpack.fleet.policyDetails.summary.autoUpgrade', { + defaultMessage: 'Auto-upgrade agents', + }), + content: ( + - - - - - - - - - } + { + setIsManageAutoUpgradeAgentsModalOpen( + !isManageAutoUpgradeAgentsModalOpen + ); + }} > - - + + + + + {agentPolicy.required_versions?.length || 0} + - {getRootIntegrations(agentPolicy.package_policies || []).length > 0 && - (agentPolicy.unprivileged_agents || 0) > 0 && ( - - - } - /> - - )} ), - }, - { isDivider: true }, - ] - : []), - { - label: i18n.translate('xpack.fleet.policyDetails.summary.lastUpdated', { - defaultMessage: 'Last updated on', - }), - content: - (agentPolicy && ( - { + history.push(getPath('policy_details', { policyId: newAgentPolicy.id })); + }} + onCancelEnrollment={onCancelEnrollment} /> - )) || - '', - }, - { isDivider: true }, - { - content: agentPolicy && ( - { - history.push(getPath('policy_details', { policyId: newAgentPolicy.id })); - }} - onCancelEnrollment={onCancelEnrollment} - /> - ), - }, - ].map((item, index) => ( - - {item.isDivider ?? false ? ( - - ) : item.label ? ( - - - {item.label} - - - {item.content} - - - ) : ( - item.content - )} - - ))} - + ), + }, + ].map((item, index) => ( + + {item.isDivider ?? false ? ( + + ) : item.label ? ( + + + {item.label} + + + {item.content} + + + ) : ( + item.content + )} + + ))} + + {isManageAutoUpgradeAgentsModalOpen && ( + + { + setIsManageAutoUpgradeAgentsModalOpen(false); + if (refreshPolicy) { + refreshAgentPolicy(); + } + }} + /> + + )} + + ); }; diff --git a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/list_page/index.test.tsx b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/list_page/index.test.tsx index 3f50ad4ac514e..2dce14662891e 100644 --- a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/list_page/index.test.tsx +++ b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/list_page/index.test.tsx @@ -19,8 +19,18 @@ jest.mock('../../../hooks', () => ({ useGetAgentPoliciesQuery: jest.fn().mockReturnValue({ data: { items: [ - { id: 'not_managed_policy', is_managed: false, updated_at: '2023-04-06T07:19:29.892Z' }, - { id: 'managed_policy', is_managed: true, updated_at: '2023-04-07T07:19:29.892Z' }, + { + id: 'not_managed_policy', + is_managed: false, + updated_at: '2023-04-06T07:19:29.892Z', + agents: 1, + }, + { + id: 'managed_policy', + is_managed: true, + updated_at: '2023-04-07T07:19:29.892Z', + agents: 1, + }, ], total: 2, } as GetAgentPoliciesResponse, diff --git a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agents/components/manage_auto_upgrade_agents_modal/index.tsx b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agents/components/manage_auto_upgrade_agents_modal/index.tsx new file mode 100644 index 0000000000000..0a52b268e6a63 --- /dev/null +++ b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agents/components/manage_auto_upgrade_agents_modal/index.tsx @@ -0,0 +1,290 @@ +/* + * 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, { useState } from 'react'; +import { + EuiButton, + EuiButtonEmpty, + EuiCallOut, + EuiConfirmModal, + EuiFieldNumber, + EuiFlexGroup, + EuiFlexItem, + EuiForm, + EuiFormRow, + EuiIconTip, + EuiSpacer, + EuiSuperSelect, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; + +import type { AgentTargetVersion } from '../../../../../../../common/types'; + +import type { AgentPolicy } from '../../../../../../../common'; +import { useGetAgentsAvailableVersionsQuery, useStartServices } from '../../../../../../hooks'; +import { checkTargetVersionsValidity } from '../../../../../../../common/services'; +import { sendUpdateAgentPolicyForRq } from '../../../../../../hooks/use_request/agent_policy'; + +export interface ManageAutoUpgradeAgentsModalProps { + onClose: (refreshPolicy: boolean) => void; + agentPolicy: AgentPolicy; + agentCount: number; +} + +export const ManageAutoUpgradeAgentsModal: React.FunctionComponent< + ManageAutoUpgradeAgentsModalProps +> = ({ onClose, agentPolicy, agentCount }) => { + const [isLoading, setIsLoading] = useState(false); + const { notifications } = useStartServices(); + const [targetVersions, setTargetVersions] = useState(agentPolicy.required_versions || []); + const { data: agentsAvailableVersions } = useGetAgentsAvailableVersionsQuery({ + enabled: true, + }); + const latestVersion = agentsAvailableVersions?.items[0]; + const [errors, setErrors] = useState([]); + + const submitUpdateAgentPolicy = async () => { + setIsLoading(true); + let isSuccess = false; + try { + await sendUpdateAgentPolicyForRq(agentPolicy.id, { + name: agentPolicy.name, + namespace: agentPolicy.namespace, + required_versions: targetVersions, + }); + notifications.toasts.addSuccess( + i18n.translate('xpack.fleet.manageAutoUpgradeAgents.successNotificationTitle', { + defaultMessage: "Successfully updated ''{name}'' auto-upgrade agents settings", + values: { name: agentPolicy.name }, + }) + ); + isSuccess = true; + } catch (e) { + notifications.toasts.addDanger( + i18n.translate('xpack.fleet.manageAutoUpgradeAgents.errorNotificationTitle', { + defaultMessage: 'Unable to update agent policy', + }) + ); + } + setIsLoading(false); + onClose(isSuccess); + }; + + async function onSubmit() { + await submitUpdateAgentPolicy(); + } + + async function updateTargetVersions(newVersions: AgentTargetVersion[]) { + const error = checkTargetVersionsValidity(newVersions); + setErrors(error ? [error] : []); + + setTargetVersions(newVersions); + } + + return ( + + } + onCancel={() => onClose(false)} + onConfirm={onSubmit} + confirmButtonDisabled={isLoading || errors.length > 0} + cancelButtonText={ + + } + confirmButtonText={ + + } + style={{ width: 1000 }} + > + + + {agentCount > 0 ? ( + <> + + + + ) : null} + + + + 0} error={errors} component="form"> + {targetVersions.map((requiredVersion, index) => ( + <> + { + updateTargetVersions(targetVersions.filter((_, i) => i !== index)); + }} + onUpdate={(version: string, percentage: number) => { + updateTargetVersions( + targetVersions.map((targetVersion, i) => + i === index ? { version, percentage } : targetVersion + ) + ); + }} + /> + + + ))} + + + + + { + updateTargetVersions([ + ...targetVersions, + { + version: latestVersion || '', + percentage: targetVersions.length === 0 ? 100 : 1, + }, + ]); + }} + iconType="plusInCircle" + > + + + + + + + ); +}; + +const TargetVersionsRow: React.FunctionComponent<{ + agentsAvailableVersions: string[]; + requiredVersion: AgentTargetVersion; + onRemove: () => void; + onUpdate: (version: string, percentage: number) => void; +}> = ({ agentsAvailableVersions, requiredVersion, onRemove, onUpdate }) => { + const options = agentsAvailableVersions.map((version) => ({ + value: version, + inputDisplay: version, + })); + + const [version, setVersion] = useState(requiredVersion.version); + + const onVersionChange = (value: string) => { + setVersion(value); + }; + + const [percentage, setPercentage] = useState(requiredVersion.percentage); + + const onPercentageChange = (value: number) => { + setPercentage(value); + }; + + return ( + + + + + + } + /> + + } + > + { + onVersionChange(value); + onUpdate(value, percentage); + }} + /> + + + + + + + } + /> + + } + > + { + const newValue = parseInt(e.target.value, 10); + onPercentageChange(newValue); + onUpdate(version, newValue); + }} + min={0} + step={1} + max={100} + required + /> + + + + + + + + + + + ); +}; diff --git a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agents/services/agent_status.tsx b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agents/services/agent_status.tsx index 2c61ab10ca78f..6e2986735d6be 100644 --- a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agents/services/agent_status.tsx +++ b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agents/services/agent_status.tsx @@ -26,19 +26,29 @@ export function getColorForAgentStatus( agentStatus: SimplifiedAgentStatus, euiTheme: EuiThemeComputed<{}> ): string { + const isAmsterdam = euiTheme.themeName === 'EUI_THEME_AMSTERDAM'; + switch (agentStatus) { case 'healthy': - return euiTheme.colors.backgroundFilledSuccess; + return isAmsterdam + ? euiTheme.colors.vis.euiColorVisBehindText0 + : euiTheme.colors.backgroundFilledSuccess; case 'offline': return euiTheme.colors.lightShade; case 'inactive': return euiTheme.colors.darkShade; case 'unhealthy': - return euiTheme.colors.backgroundFilledWarning; + return isAmsterdam + ? euiTheme.colors.vis.euiColorVisBehindText5 + : euiTheme.colors.backgroundFilledWarning; case 'orphaned': - return euiTheme.colors.backgroundFilledWarning; + return isAmsterdam + ? euiTheme.colors.vis.euiColorVisBehindText5 + : euiTheme.colors.backgroundFilledWarning; case 'updating': - return euiTheme.colors.backgroundFilledPrimary; + return isAmsterdam + ? euiTheme.colors.vis.euiColorVisBehindText1 + : euiTheme.colors.backgroundFilledPrimary; case 'unenrolled': return euiTheme.colors.backgroundBaseDisabled; case 'uninstalled': diff --git a/x-pack/platform/plugins/shared/fleet/public/constants/index.ts b/x-pack/platform/plugins/shared/fleet/public/constants/index.ts index 059bae6ea7bff..0f4481cc4be96 100644 --- a/x-pack/platform/plugins/shared/fleet/public/constants/index.ts +++ b/x-pack/platform/plugins/shared/fleet/public/constants/index.ts @@ -55,6 +55,7 @@ export const TOUR_STORAGE_KEYS = { INACTIVE_AGENTS: 'fleet.inactiveAgentsTour', GRANULAR_PRIVILEGES: 'fleet.granularPrivileges', AGENT_EXPORT_CSV: 'fleet.agentExportCSVTour', + AUTO_UPGRADE_AGENTS: 'fleet.autoUpgradeAgentsTour', }; export interface TourConfig { diff --git a/x-pack/platform/plugins/shared/fleet/public/hooks/use_request/agent_policy.ts b/x-pack/platform/plugins/shared/fleet/public/hooks/use_request/agent_policy.ts index e130eae49c6eb..3bf3468370685 100644 --- a/x-pack/platform/plugins/shared/fleet/public/hooks/use_request/agent_policy.ts +++ b/x-pack/platform/plugins/shared/fleet/public/hooks/use_request/agent_policy.ts @@ -156,6 +156,18 @@ export const sendUpdateAgentPolicy = ( }); }; +export const sendUpdateAgentPolicyForRq = ( + agentPolicyId: string, + body: UpdateAgentPolicyRequest['body'] +) => { + return sendRequestForRq({ + path: agentPolicyRouteService.getUpdatePath(agentPolicyId), + method: 'put', + body: JSON.stringify(body), + version: API_VERSIONS.public.v1, + }); +}; + export const sendCopyAgentPolicy = ( agentPolicyId: string, body: CopyAgentPolicyRequest['body'] diff --git a/x-pack/platform/plugins/shared/fleet/public/hooks/use_request/agents.ts b/x-pack/platform/plugins/shared/fleet/public/hooks/use_request/agents.ts index 98e71732c34c8..b893d723be691 100644 --- a/x-pack/platform/plugins/shared/fleet/public/hooks/use_request/agents.ts +++ b/x-pack/platform/plugins/shared/fleet/public/hooks/use_request/agents.ts @@ -351,6 +351,21 @@ export function sendGetAgentsAvailableVersions() { }); } +export function useGetAgentsAvailableVersionsQuery(options: Partial<{ enabled: boolean }> = {}) { + return useQuery( + ['available_versions'], + () => + sendRequestForRq({ + method: 'get', + path: agentRouteService.getAvailableVersionsPath(), + version: API_VERSIONS.public.v1, + }), + { + enabled: options.enabled, + } + ); +} + export function sendGetAgentStatusRuntimeField() { return sendRequestForRq({ method: 'get', diff --git a/x-pack/platform/plugins/shared/fleet/scripts/verify_test_packages/verify_test_packages.test.ts b/x-pack/platform/plugins/shared/fleet/scripts/verify_test_packages/verify_test_packages.test.ts index 4f15ea3e6558f..920a4d0c6d621 100644 --- a/x-pack/platform/plugins/shared/fleet/scripts/verify_test_packages/verify_test_packages.test.ts +++ b/x-pack/platform/plugins/shared/fleet/scripts/verify_test_packages/verify_test_packages.test.ts @@ -12,7 +12,12 @@ import type { Logger } from '@kbn/core/server'; import { appContextService } from '../../server/services/app_context'; -import { verifyAllTestPackages } from './verify_test_packages'; +import { + getAllTestPackagesPaths, + getAllTestPackagesZip, + verifyTestPackage, + verifyTestPackageFromPath, +} from './verify_test_packages'; jest.mock('../../server/services/app_context'); @@ -23,15 +28,21 @@ mockedAppContextService.getSecuritySetup.mockImplementation(() => ({ let mockedLogger: jest.Mocked; -// FLAKY: https://github.com/elastic/kibana/issues/200787 -describe.skip('Test packages', () => { +describe('Test packages', () => { beforeEach(() => { mockedLogger = loggerMock.create(); mockedAppContextService.getLogger.mockReturnValue(mockedLogger); }); - test('All test packages should be valid (node scripts/verify_test_packages) ', async () => { - const { errors } = await verifyAllTestPackages(); - expect(errors).toEqual([]); - }); + for (const zip of getAllTestPackagesZip()) { + test(`${zip} should be a valid package`, async () => { + await verifyTestPackage(zip); + }); + } + + for (const { topLevelDir, paths } of getAllTestPackagesPaths()) { + test(`${topLevelDir} should be a valid package`, async () => { + await verifyTestPackageFromPath(paths, topLevelDir); + }); + } }); diff --git a/x-pack/platform/plugins/shared/fleet/scripts/verify_test_packages/verify_test_packages.ts b/x-pack/platform/plugins/shared/fleet/scripts/verify_test_packages/verify_test_packages.ts index 33ac12a6cade3..c26dbc0dd7245 100644 --- a/x-pack/platform/plugins/shared/fleet/scripts/verify_test_packages/verify_test_packages.ts +++ b/x-pack/platform/plugins/shared/fleet/scripts/verify_test_packages/verify_test_packages.ts @@ -15,13 +15,13 @@ import type { Logger } from '@kbn/core/server'; import { ToolingLog } from '@kbn/tooling-log'; import { - _generatePackageInfoFromPaths, generatePackageInfoFromArchiveBuffer, + _generatePackageInfoFromPaths, } from '../../server/services/epm/archive/parse'; const readFileAsync = promisify(readFile); -const TEST_PACKAGE_DIRECTORIES = [ +export const TEST_PACKAGE_DIRECTORIES = [ '../../../../../../test/fleet_api_integration/apis/fixtures/bundled_packages', '../../../../../../test/fleet_api_integration/apis/fixtures/test_packages', '../../../../../../test/fleet_api_integration/apis/fixtures/package_verification/packages', @@ -62,43 +62,77 @@ export const run = async () => { } }; +export async function verifyTestPackage(zipPath: string, logger?: ToolingLog | Logger) { + const buffer = await readFileAsync(zipPath); + try { + const { packageInfo } = await generatePackageInfoFromArchiveBuffer(buffer, 'application/zip'); + logger?.info(`Successfully parsed zip pkg ${packageInfo.name}-${packageInfo.version}`); + } catch (e) { + logger?.error(`Error parsing ${zipPath} : ${e}`); + throw e; + } +} + +export async function verifyTestPackageFromPath( + packagePaths: string[], + topLevelDir: string, + logger?: ToolingLog | Logger +) { + try { + const packageInfo = await _generatePackageInfoFromPaths(packagePaths, topLevelDir); + logger?.info(`Successfully parsed zip pkg ${packageInfo.name}-${packageInfo.version}`); + } catch (e) { + logger?.error(`Error parsing ${topLevelDir} : ${e}`); + throw e; + } +} + +export function getAllTestPackagesZip() { + return TEST_PACKAGE_DIRECTORIES.reduce((acc, dir) => { + const packageVersionPaths = getAllPackagesFromDir(path.join(__dirname, dir)); + const [zips] = partition(packageVersionPaths, (p) => p.endsWith('.zip')); + + return [...acc, ...zips]; + }, [] as string[]); +} + +export function getAllTestPackagesPaths() { + return TEST_PACKAGE_DIRECTORIES.reduce((acc, dir) => { + const packageVersionPaths = getAllPackagesFromDir(path.join(__dirname, dir)); + const [_, dirs] = partition(packageVersionPaths, (p) => p.endsWith('.zip')); + + const allPackageDirPaths = dirs.map(getAllPathsFromDir); + return [ + ...acc, + ...[...allPackageDirPaths.entries()].map(([i, paths]) => ({ + topLevelDir: packageVersionPaths[i], + paths, + })), + ]; + }, [] as Array<{ topLevelDir: string; paths: string[] }>); +} + export const verifyAllTestPackages = async ( logger?: ToolingLog | Logger ): Promise<{ successCount: number; errors: Error[] }> => { const errors = []; let successCount = 0; - for (const dir of TEST_PACKAGE_DIRECTORIES) { - const packageVersionPaths = getAllPackagesFromDir(path.join(__dirname, dir)); - const [zips, dirs] = partition(packageVersionPaths, (p) => p.endsWith('.zip')); - - for (const zipPath of zips) { - const buffer = await readFileAsync(zipPath); - - try { - const { packageInfo } = await generatePackageInfoFromArchiveBuffer( - buffer, - 'application/zip' - ); - logger?.info(`Successfully parsed zip pkg ${packageInfo.name}-${packageInfo.version}`); - successCount++; - } catch (e) { - logger?.error(`Error parsing ${zipPath} : ${e}`); - errors.push(e); - } + for (const zipPath of getAllTestPackagesZip()) { + try { + await verifyTestPackage(zipPath, logger); + successCount++; + } catch (e) { + errors.push(e); } + } - const allPackageDirPaths = dirs.map(getAllPathsFromDir); - for (const [i, packagePaths] of allPackageDirPaths.entries()) { - const topLevelDir = packageVersionPaths[i]; - try { - const packageInfo = await _generatePackageInfoFromPaths(packagePaths, topLevelDir); - logger?.info(`Successfully parsed ${packageInfo.name}-${packageInfo.version}`); - successCount++; - } catch (e) { - logger?.error(`Error parsing ${topLevelDir} : ${e}`); - errors.push(e); - } + for (const { topLevelDir, paths } of getAllTestPackagesPaths()) { + try { + await verifyTestPackageFromPath(paths, topLevelDir, logger); + successCount++; + } catch (e) { + errors.push(e); } } diff --git a/x-pack/platform/plugins/shared/fleet/server/constants/fleet_es_assets.ts b/x-pack/platform/plugins/shared/fleet/server/constants/fleet_es_assets.ts index 384a77afd112e..130f90f8aabda 100644 --- a/x-pack/platform/plugins/shared/fleet/server/constants/fleet_es_assets.ts +++ b/x-pack/platform/plugins/shared/fleet/server/constants/fleet_es_assets.ts @@ -11,7 +11,7 @@ import { getESAssetMetadata } from '../services/epm/elasticsearch/meta'; const meta = getESAssetMetadata(); -export const FLEET_INSTALL_FORMAT_VERSION = '1.4.0'; +export const FLEET_INSTALL_FORMAT_VERSION = '1.4.1'; export const FLEET_AGENT_POLICIES_SCHEMA_VERSION = '1.1.1'; diff --git a/x-pack/platform/plugins/shared/fleet/server/saved_objects/index.ts b/x-pack/platform/plugins/shared/fleet/server/saved_objects/index.ts index 2dfdf333fd72d..e6695fc5bb2e2 100644 --- a/x-pack/platform/plugins/shared/fleet/server/saved_objects/index.ts +++ b/x-pack/platform/plugins/shared/fleet/server/saved_objects/index.ts @@ -247,6 +247,10 @@ export const getSavedObjectTypes = ( advanced_settings: { type: 'flattened', index: false }, supports_agentless: { type: 'boolean' }, global_data_tags: { type: 'flattened', index: false }, + agentless: { + dynamic: false, + properties: {}, + }, monitoring_pprof_enabled: { type: 'boolean', index: false }, monitoring_http: { type: 'flattened', index: false }, monitoring_diagnostics: { type: 'flattened', index: false }, @@ -314,6 +318,19 @@ export const getSavedObjectTypes = ( }, ], }, + '6': { + changes: [ + { + type: 'mappings_addition', + addedMappings: { + agentless: { + dynamic: false, + properties: {}, + }, + }, + }, + ], + }, }, }, [AGENT_POLICY_SAVED_OBJECT_TYPE]: { @@ -358,6 +375,10 @@ export const getSavedObjectTypes = ( advanced_settings: { type: 'flattened', index: false }, supports_agentless: { type: 'boolean' }, global_data_tags: { type: 'flattened', index: false }, + agentless: { + dynamic: false, + properties: {}, + }, }, }, modelVersions: { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agent_policies/required_versions.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/agent_policies/required_versions.test.ts index 1a97169c69729..35c413be4fafa 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agent_policies/required_versions.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agent_policies/required_versions.test.ts @@ -40,7 +40,7 @@ describe('validateRequiredVersions', () => { ]); }).toThrow( new AgentPolicyInvalidError( - `Policy "test policy" failed validation: duplicate versions not allowed in required_versions` + `Policy "test policy" failed required_versions validation: duplicate versions not allowed` ) ); }); @@ -53,7 +53,7 @@ describe('validateRequiredVersions', () => { ]); }).toThrow( new AgentPolicyInvalidError( - `Policy "test policy" failed validation: invalid semver version 9.0.0invalid in required_versions` + `Policy "test policy" failed required_versions validation: invalid semver version 9.0.0invalid` ) ); }); @@ -66,7 +66,20 @@ describe('validateRequiredVersions', () => { ]); }).toThrow( new AgentPolicyInvalidError( - `Policy "test policy" failed validation: sum of required_versions percentages cannot exceed 100` + `Policy "test policy" failed required_versions validation: sum of percentages cannot exceed 100` + ) + ); + }); + + it('should throw error if percentage is 0 or undefined', () => { + expect(() => { + validateRequiredVersions('test policy', [ + { version: '9.0.0', percentage: 100 }, + { version: '9.1.0', percentage: 0 }, + ]); + }).toThrow( + new AgentPolicyInvalidError( + `Policy "test policy" failed required_versions validation: percentage is required` ) ); }); diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agent_policies/required_versions.ts b/x-pack/platform/plugins/shared/fleet/server/services/agent_policies/required_versions.ts index 1b12c9b5c4307..f2b93c77e3a04 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agent_policies/required_versions.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agent_policies/required_versions.ts @@ -5,12 +5,11 @@ * 2.0. */ -import semverValid from 'semver/functions/valid'; - import type { AgentTargetVersion } from '../../../common/types'; import { AgentPolicyInvalidError } from '../../errors'; import { appContextService } from '..'; +import { checkTargetVersionsValidity } from '../../../common/services/agent_utils'; export function validateRequiredVersions( name: string, @@ -24,24 +23,10 @@ export function validateRequiredVersions( `Policy "${name}" failed validation: required_versions are not allowed when automatic upgrades feature is disabled` ); } - const versions = requiredVersions.map((v) => v.version); - const uniqueVersions = new Set(versions); - if (versions.length !== uniqueVersions.size) { - throw new AgentPolicyInvalidError( - `Policy "${name}" failed validation: duplicate versions not allowed in required_versions` - ); - } - versions.forEach((version) => { - if (!semverValid(version)) { - throw new AgentPolicyInvalidError( - `Policy "${name}" failed validation: invalid semver version ${version} in required_versions` - ); - } - }); - const sumOfPercentages = requiredVersions.reduce((acc, v) => acc + v.percentage, 0); - if (sumOfPercentages > 100) { + const error = checkTargetVersionsValidity(requiredVersions); + if (error) { throw new AgentPolicyInvalidError( - `Policy "${name}" failed validation: sum of required_versions percentages cannot exceed 100` + `Policy "${name}" failed required_versions validation: ${error}` ); } } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.ts b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.ts index da9f61fbefe4f..0fbb8886f1d61 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.ts @@ -821,6 +821,7 @@ class AgentPolicyService { 'fleet_server_host_id', 'supports_agentless', 'global_data_tags', + 'agentless', 'monitoring_pprof_enabled', 'monitoring_http', 'monitoring_diagnostics', diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agents/agentless_agent.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/agents/agentless_agent.test.ts index 042f9dce7f772..9cf952c9d94c7 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agents/agentless_agent.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agents/agentless_agent.test.ts @@ -285,6 +285,119 @@ describe('Agentless Agent service', () => { ); }); + it('should create agentless agent with resources', async () => { + const returnValue = { + id: 'mocked', + regional_id: 'mocked', + }; + + (axios as jest.MockedFunction).mockResolvedValueOnce(returnValue); + const soClient = getAgentPolicyCreateMock(); + // ignore unrelated unique name constraint + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + jest.spyOn(appContextService, 'getConfig').mockReturnValue({ + agentless: { + enabled: true, + api: { + url: 'http://api.agentless.com', + tls: { + certificate: '/path/to/cert', + key: '/path/to/key', + ca: '/path/to/ca', + }, + }, + }, + } as any); + jest + .spyOn(appContextService, 'getCloud') + .mockReturnValue({ isCloudEnabled: true, isServerlessEnabled: true } as any); + jest + .spyOn(appContextService, 'getKibanaVersion') + .mockReturnValue('mocked-kibana-version-infinite'); + mockedListFleetServerHosts.mockResolvedValue({ + items: [ + { + id: 'mocked-fleet-server-id', + host: 'http://fleetserver:8220', + active: true, + is_default: true, + host_urls: ['http://fleetserver:8220'], + }, + ], + } as any); + mockedListEnrollmentApiKeys.mockResolvedValue({ + items: [ + { + id: 'mocked-fleet-enrollment-token-id', + policy_id: 'mocked-fleet-enrollment-policy-id', + api_key: 'mocked-fleet-enrollment-api-key', + }, + ], + } as any); + + const createAgentlessAgentReturnValue = await agentlessAgentService.createAgentlessAgent( + esClient, + soClient, + { + id: 'mocked-agentless-agent-policy-id', + name: 'agentless agent policy', + namespace: 'default', + supports_agentless: true, + agentless: { + resources: { + requests: { + memory: '1Gi', + cpu: '500m', + }, + }, + }, + global_data_tags: [ + { + name: 'organization', + value: 'elastic', + }, + { + name: 'division', + value: 'cloud', + }, + { + name: 'team', + value: 'fleet', + }, + ], + } as AgentPolicy + ); + + expect(axios).toHaveBeenCalledTimes(1); + expect(createAgentlessAgentReturnValue).toEqual(returnValue); + expect(axios).toHaveBeenCalledWith( + expect.objectContaining({ + data: { + fleet_token: 'mocked-fleet-enrollment-api-key', + fleet_url: 'http://fleetserver:8220', + policy_id: 'mocked-agentless-agent-policy-id', + resources: { + requests: { + memory: '1Gi', + cpu: '500m', + }, + }, + labels: { + owner: { + org: 'elastic', + division: 'cloud', + team: 'fleet', + }, + }, + }, + headers: expect.anything(), + httpsAgent: expect.anything(), + method: 'POST', + url: 'http://api.agentless.com/api/v1/serverless/deployments', + }) + ); + }); + it('should create agentless agent when no labels are given', async () => { const returnValue = { id: 'mocked', diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agents/agentless_agent.ts b/x-pack/platform/plugins/shared/fleet/server/services/agents/agentless_agent.ts index 3d6c8bba563ab..ab65d497ba525 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agents/agentless_agent.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agents/agentless_agent.ts @@ -110,6 +110,7 @@ class AgentlessAgentService { policy_id: policyId, fleet_url: fleetUrl, fleet_token: fleetToken, + resources: agentlessAgentPolicy.agentless?.resources, labels, }, method: 'POST', diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/template/template.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/template/template.ts index 81d280031d2c7..6c402ed0851eb 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/template/template.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/template/template.ts @@ -1163,7 +1163,8 @@ const updateExistingDataStream = async ({ // Trigger a rollover if the index mode or source type has changed if ( currentIndexMode !== settings?.index?.mode || - currentSourceType !== settings?.index?.source?.mode || + // @ts-expect-error Property 'source.mode' does not exist on type 'IndicesMappingLimitSettings' + currentSourceType !== settings?.index?.mapping?.source?.mode || dynamicDimensionMappingsChanged ) { if (options?.skipDataStreamRollover === true) { diff --git a/x-pack/platform/plugins/shared/fleet/server/telemetry/sender.test.ts b/x-pack/platform/plugins/shared/fleet/server/telemetry/sender.test.ts index 0f79cd8464e3e..978bcda2dbbc6 100644 --- a/x-pack/platform/plugins/shared/fleet/server/telemetry/sender.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/telemetry/sender.test.ts @@ -15,6 +15,8 @@ import type { InfoResponse } from '@elastic/elasticsearch/lib/api/types'; import { loggingSystemMock } from '@kbn/core/server/mocks'; +import { Observable } from 'rxjs'; + import { UpdateEventType } from '../services/upgrade_sender'; import { TelemetryEventsSender } from './sender'; @@ -63,6 +65,7 @@ describe('TelemetryEventsSender', () => { it('should send events when due', async () => { sender['telemetryStart'] = { getIsOptedIn: jest.fn(async () => true), + isOptedIn$: new Observable(), }; sender['telemetrySetup'] = { getTelemetryUrl: jest.fn( @@ -93,6 +96,7 @@ describe('TelemetryEventsSender', () => { it("shouldn't send when telemetry is disabled", async () => { const telemetryStart = { getIsOptedIn: jest.fn(async () => false), + isOptedIn$: new Observable(), }; sender['telemetryStart'] = telemetryStart; @@ -115,6 +119,7 @@ describe('TelemetryEventsSender', () => { it('should send events to separate channels', async () => { sender['telemetryStart'] = { getIsOptedIn: jest.fn(async () => true), + isOptedIn$: new Observable(), }; sender['telemetrySetup'] = { getTelemetryUrl: jest.fn( diff --git a/x-pack/platform/plugins/shared/fleet/server/types/models/agent_policy.test.ts b/x-pack/platform/plugins/shared/fleet/server/types/models/agent_policy.test.ts index 2dea7144df4f5..2b93f1be0ab6b 100644 --- a/x-pack/platform/plugins/shared/fleet/server/types/models/agent_policy.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/types/models/agent_policy.test.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { GlobalDataTag } from '../../../common/types'; +import type { AgentlessPolicy, GlobalDataTag } from '../../../common/types'; import { AgentPolicyBaseSchema } from './agent_policy'; @@ -91,5 +91,56 @@ describe('AgentPolicyBaseSchema', () => { AgentPolicyBaseSchema.global_data_tags.validate(tags); }).not.toThrow(); }); + + it('should not throw an error if provided with empty agentless resources', () => { + const agentless: AgentlessPolicy = {}; + + expect(() => { + AgentPolicyBaseSchema.agentless.validate(agentless); + }).not.toThrow(); + }); + + it('should not throw an error if provided with valid agentless resources', () => { + const agentless: AgentlessPolicy = { + resources: { + requests: { + memory: '1Gi', + cpu: '1', + }, + }, + }; + + expect(() => { + AgentPolicyBaseSchema.agentless.validate(agentless); + }).not.toThrow(); + }); + + it('should throw an error if provided with invalid agentless memory', () => { + const agentless: AgentlessPolicy = { + resources: { + requests: { + memory: '1', + }, + }, + }; + + expect(() => { + AgentPolicyBaseSchema.agentless.validate(agentless); + }).toThrow(); + }); + + it('should throw an error if provided with invalid agentless CPU', () => { + const agentless: AgentlessPolicy = { + resources: { + requests: { + cpu: '1CPU', + }, + }, + }; + + expect(() => { + AgentPolicyBaseSchema.agentless.validate(agentless); + }).toThrow(); + }); }); }); diff --git a/x-pack/platform/plugins/shared/fleet/server/types/models/agent_policy.ts b/x-pack/platform/plugins/shared/fleet/server/types/models/agent_policy.ts index 42069fa29a028..c6e82b5395f06 100644 --- a/x-pack/platform/plugins/shared/fleet/server/types/models/agent_policy.ts +++ b/x-pack/platform/plugins/shared/fleet/server/types/models/agent_policy.ts @@ -39,6 +39,20 @@ function isInteger(n: number) { } } +const memoryRegex = /^\d+(Mi|Gi)$/; +function validateMemory(s: string) { + if (!memoryRegex.test(s)) { + return 'Invalid memory format'; + } +} + +const cpuRegex = /^(\d+m|\d+(\.\d+)?)$/; +function validateCPU(s: string) { + if (!cpuRegex.test(s)) { + return 'Invalid CPU format'; + } +} + export const AgentPolicyBaseSchema = { id: schema.maybe(schema.string()), space_ids: schema.maybe(schema.arrayOf(schema.string())), @@ -132,6 +146,20 @@ export const AgentPolicyBaseSchema = { } ) ), + agentless: schema.maybe( + schema.object({ + resources: schema.maybe( + schema.object({ + requests: schema.maybe( + schema.object({ + memory: schema.maybe(schema.string({ validate: validateMemory })), + cpu: schema.maybe(schema.string({ validate: validateCPU })), + }) + ), + }) + ), + }) + ), monitoring_pprof_enabled: schema.maybe(schema.boolean()), monitoring_http: schema.maybe( schema.object({ @@ -381,6 +409,7 @@ export const FullAgentPolicyResponseSchema = schema.object({ metrics: schema.boolean(), logs: schema.boolean(), traces: schema.boolean(), + apm: schema.maybe(schema.any()), }), download: schema.object({ sourceURI: schema.string(), diff --git a/x-pack/platform/plugins/shared/fleet/server/types/so_attributes.ts b/x-pack/platform/plugins/shared/fleet/server/types/so_attributes.ts index 6f415eea9eb61..7998e5da9b5e5 100644 --- a/x-pack/platform/plugins/shared/fleet/server/types/so_attributes.ts +++ b/x-pack/platform/plugins/shared/fleet/server/types/so_attributes.ts @@ -17,6 +17,7 @@ import type { KafkaConnectionTypeType, AgentUpgradeDetails, OutputPreset, + AgentlessPolicy, } from '../../common/types'; import type { AgentType, FleetServerAgentComponent } from '../../common/types/models'; @@ -65,6 +66,7 @@ export interface AgentPolicySOAttributes { agents?: number; overrides?: any | null; global_data_tags?: Array<{ name: string; value: string | number }>; + agentless?: AgentlessPolicy; version?: string; } diff --git a/x-pack/platform/plugins/shared/index_management/__jest__/client_integration/helpers/test_subjects.ts b/x-pack/platform/plugins/shared/index_management/__jest__/client_integration/helpers/test_subjects.ts index c758e53804c73..0862977d3bf2e 100644 --- a/x-pack/platform/plugins/shared/index_management/__jest__/client_integration/helpers/test_subjects.ts +++ b/x-pack/platform/plugins/shared/index_management/__jest__/client_integration/helpers/test_subjects.ts @@ -94,6 +94,7 @@ export type TestSubjects = | 'editDataRetentionButton' | 'bulkEditDataRetentionButton' | 'dataStreamActionsPopoverButton' + | 'reducedDataRetentionCallout' | 'errorWhenCreatingCallout' | 'manageDataStreamButton' | 'dataRetentionValue' diff --git a/x-pack/platform/plugins/shared/index_management/__jest__/client_integration/home/data_streams_tab.test.ts b/x-pack/platform/plugins/shared/index_management/__jest__/client_integration/home/data_streams_tab.test.ts index d43e29911890a..0ab31434ae8ac 100644 --- a/x-pack/platform/plugins/shared/index_management/__jest__/client_integration/home/data_streams_tab.test.ts +++ b/x-pack/platform/plugins/shared/index_management/__jest__/client_integration/home/data_streams_tab.test.ts @@ -535,6 +535,30 @@ describe('Data Streams tab', () => { testBed.component.update(); }); + test('shows bulk edit callout for reduced data retention', async () => { + const { + actions: { selectDataStream, clickBulkEditDataRetentionButton }, + } = testBed; + + selectDataStream('dataStream1', true); + selectDataStream('dataStream2', true); + + clickBulkEditDataRetentionButton(); + + // Decrease data retention value to 5d (it was 7d initially) + testBed.form.setInputValue('dataRetentionValue', '5'); + + // Verify that callout is displayed + expect(testBed.exists('reducedDataRetentionCallout')).toBeTruthy(); + + // Verify message in callout + const calloutText = testBed.find('reducedDataRetentionCallout').text(); + expect(calloutText).toContain( + 'The retention period will be reduced for 2 data streams. Data older than then new retention period will be permanently deleted.' + ); + expect(calloutText).toContain('Affected data streams: dataStream1, dataStream2'); + }); + test('can set data retention period for mutliple data streams', async () => { const { actions: { selectDataStream, clickBulkEditDataRetentionButton }, @@ -798,6 +822,28 @@ describe('Data Streams tab', () => { expect.objectContaining({ body: JSON.stringify({ dataStreams: ['dataStream1'] }) }) ); }); + + test('shows single edit callout for reduced data retention', async () => { + const { + actions: { clickNameAt, clickEditDataRetentionButton }, + } = testBed; + + await clickNameAt(0); + + clickEditDataRetentionButton(); + + // Decrease data retention value to 5d (it was 7d initially) + testBed.form.setInputValue('dataRetentionValue', '5'); + + // Verify that callout is displayed + expect(testBed.exists('reducedDataRetentionCallout')).toBeTruthy(); + + // Verify message in callout + const calloutText = testBed.find('reducedDataRetentionCallout').text(); + expect(calloutText).toContain( + 'The retention period will be reduced. Data older than then new retention period will be permanently deleted.' + ); + }); }); test('clicking index template name navigates to the index template details', async () => { diff --git a/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx b/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx index cb8a1efbf9c70..1a99d74e6bb13 100644 --- a/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx +++ b/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx @@ -29,6 +29,14 @@ describe('Mappings editor: core', () => { let getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); let testBed: MappingsEditorTestBed; const appDependencies = { + core: { application: {} }, + docLinks: { + links: { + inferenceManagement: { + inferenceAPIDocumentation: 'https://abc.com/inference-api-create', + }, + }, + }, plugins: { ml: { mlApi: {} }, }, @@ -474,6 +482,40 @@ describe('Mappings editor: core', () => { expect(data).toEqual(updatedMappings); }); + test('updates mapping without inference id for semantic_text field', async () => { + let updatedMappings = { ...defaultMappings }; + + const { + find, + actions: { addField }, + component, + } = testBed; + + /** + * Mapped fields + */ + await act(async () => { + find('addFieldButton').simulate('click'); + jest.advanceTimersByTime(0); // advance timers to allow the form to validate + }); + component.update(); + + const newField = { name: 'someNewField', type: 'semantic_text' }; + await addField(newField.name, newField.type); + + updatedMappings = { + ...updatedMappings, + properties: { + ...updatedMappings.properties, + [newField.name]: { reference_field: 'address.city', type: 'semantic_text' }, + }, + }; + + ({ data } = await getMappingsEditorData(component)); + + expect(data).toEqual(updatedMappings); + }); + describe('props.indexMode sets the correct default value of _source field', () => { it("defaults to 'stored' with 'standard' index mode prop", async () => { await act(async () => { diff --git a/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx b/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx index 0289f07534d35..3d9122f961bfe 100644 --- a/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx +++ b/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx @@ -106,7 +106,7 @@ export const CreateField = React.memo(function CreateFieldComponent({ } }; - const { createInferenceEndpoint, handleSemanticText } = useSemanticText({ + const { createInferenceEndpoint } = useSemanticText({ form, setErrorsInTrainedModelDeployment, ml, @@ -130,8 +130,9 @@ export const CreateField = React.memo(function CreateFieldComponent({ const { isValid, data } = await form.submit(); if (isValid && !clickOutside) { - if (isSemanticTextField(data)) { - handleSemanticText(data); + if (isSemanticTextField(data) && !data.inference_id) { + const { inference_id: inferenceId, ...rest } = data; + dispatch({ type: 'field.add', value: rest }); } else { dispatch({ type: 'field.add', value: data }); } diff --git a/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx b/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx index 505ca26ce7ca4..691e7da4a7254 100644 --- a/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx +++ b/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx @@ -293,11 +293,11 @@ function FieldListItemComponent( - {isSemanticText && ( + {isSemanticText && source.inference_id ? ( {source.inference_id as string} - )} + ) : null} {isShadowed && ( diff --git a/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/lib/utils.ts b/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/lib/utils.ts index e6e9ac54d3eb3..f0256ffe3ee3e 100644 --- a/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/lib/utils.ts +++ b/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/lib/utils.ts @@ -689,7 +689,7 @@ export const getAllFieldTypesFromState = (allFields: Fields): DataType[] => { }; export function isSemanticTextField(field: Partial): field is SemanticTextField { - return Boolean(field.inference_id && field.type === 'semantic_text'); + return field.type === 'semantic_text'; } /** diff --git a/x-pack/platform/plugins/shared/index_management/public/application/components/template_form/steps/step_review.tsx b/x-pack/platform/plugins/shared/index_management/public/application/components/template_form/steps/step_review.tsx index 4e1901538cb93..053a44e75effa 100644 --- a/x-pack/platform/plugins/shared/index_management/public/application/components/template_form/steps/step_review.tsx +++ b/x-pack/platform/plugins/shared/index_management/public/application/components/template_form/steps/step_review.tsx @@ -387,6 +387,7 @@ export const StepReview: React.FunctionComponent = React.memo( defaultMessage: 'Request', }), content: , + 'data-test-subj': 'stepReviewRequestTab', }, ]; @@ -397,6 +398,7 @@ export const StepReview: React.FunctionComponent = React.memo( defaultMessage: 'Preview', }), content: , + 'data-test-subj': 'stepReviewPreviewTab', }); } diff --git a/x-pack/platform/plugins/shared/index_management/public/application/constants/index.ts b/x-pack/platform/plugins/shared/index_management/public/application/constants/index.ts index f72e56310a9c7..04b30a168e983 100644 --- a/x-pack/platform/plugins/shared/index_management/public/application/constants/index.ts +++ b/x-pack/platform/plugins/shared/index_management/public/application/constants/index.ts @@ -10,3 +10,5 @@ export const REACT_ROOT_ID = 'indexManagementReactRoot'; export const ENRICH_POLICIES_REQUIRED_PRIVILEGES = ['manage_enrich']; export * from './ilm_locator'; + +export * from './ingest_pipelines_locator'; diff --git a/x-pack/platform/plugins/shared/index_management/public/application/constants/ingest_pipelines_locator.ts b/x-pack/platform/plugins/shared/index_management/public/application/constants/ingest_pipelines_locator.ts new file mode 100644 index 0000000000000..5d6037d2e3472 --- /dev/null +++ b/x-pack/platform/plugins/shared/index_management/public/application/constants/ingest_pipelines_locator.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const INGEST_PIPELINES_LOCATOR_ID = 'INGEST_PIPELINES_APP_LOCATOR'; +export const INGEST_PIPELINES_EDIT = 'pipeline_edit'; +export const INGEST_PIPELINES_LIST = 'pipelines_list'; diff --git a/x-pack/platform/plugins/shared/index_management/public/application/mount_management_section.ts b/x-pack/platform/plugins/shared/index_management/public/application/mount_management_section.ts index 003f5279ae520..4cc57c2b06a07 100644 --- a/x-pack/platform/plugins/shared/index_management/public/application/mount_management_section.ts +++ b/x-pack/platform/plugins/shared/index_management/public/application/mount_management_section.ts @@ -5,6 +5,7 @@ * 2.0. */ +import '../index.scss'; import { i18n } from '@kbn/i18n'; import SemVer from 'semver/classes/semver'; import { CoreSetup, CoreStart, ScopedHistory } from '@kbn/core/public'; diff --git a/x-pack/platform/plugins/shared/index_management/public/application/sections/home/data_stream_list/edit_data_retention_modal/edit_data_retention_modal.tsx b/x-pack/platform/plugins/shared/index_management/public/application/sections/home/data_stream_list/edit_data_retention_modal/edit_data_retention_modal.tsx index 55d8348400f5f..8d50b6c695105 100644 --- a/x-pack/platform/plugins/shared/index_management/public/application/sections/home/data_stream_list/edit_data_retention_modal/edit_data_retention_modal.tsx +++ b/x-pack/platform/plugins/shared/index_management/public/application/sections/home/data_stream_list/edit_data_retention_modal/edit_data_retention_modal.tsx @@ -201,16 +201,23 @@ export const EditDataRetentionModal: React.FunctionComponent = ({ onClose()} data-test-subj="editDataRetentionModal" - css={{ minWidth: isBulkEdit ? 650 : 450, maxWidth: 650 }} + css={{ width: 650 }} >
- + {isBulkEdit ? ( + + ) : ( + + )} @@ -292,7 +299,7 @@ export const EditDataRetentionModal: React.FunctionComponent = ({ ) } componentProps={{ - fullWidth: isBulkEdit, + fullWidth: true, euiFieldProps: { disabled: formData.infiniteRetentionPeriod || @@ -343,7 +350,7 @@ export const EditDataRetentionModal: React.FunctionComponent = ({ - {isBulkEdit && affectedDataStreams.length > 0 && !formData.infiniteRetentionPeriod && ( + {affectedDataStreams.length > 0 && !formData.infiniteRetentionPeriod && ( = ({ )} color="danger" iconType="warning" + data-test-subj="reducedDataRetentionCallout" >

- + values={{ + affectedDataStreamCount: affectedDataStreams.length, + }} + /> + ) : ( + + )}

- {affectedDataStreams.length <= 10 && ( + {isBulkEdit && affectedDataStreams.length <= 10 && (

field.inference_id) .filter( (inferenceId: string) => + inferenceId && inferenceToModelIdMap?.[inferenceId].trainedModelId && // third-party inference models don't have trainedModelId !inferenceToModelIdMap?.[inferenceId].isDeployed && !isInferencePreconfigured(inferenceId) diff --git a/x-pack/platform/plugins/shared/index_management/public/application/sections/home/template_list/template_details/tabs/tab_summary.tsx b/x-pack/platform/plugins/shared/index_management/public/application/sections/home/template_list/template_details/tabs/tab_summary.tsx index a6fbe93642813..83c60f3d04220 100644 --- a/x-pack/platform/plugins/shared/index_management/public/application/sections/home/template_list/template_details/tabs/tab_summary.tsx +++ b/x-pack/platform/plugins/shared/index_management/public/application/sections/home/template_list/template_details/tabs/tab_summary.tsx @@ -25,8 +25,9 @@ import { useAppContext } from '../../../../../app_context'; import { serializeAsESLifecycle } from '../../../../../../../common/lib'; import { getLifecycleValue } from '../../../../../lib/data_streams'; import { TemplateDeserialized } from '../../../../../../../common'; -import { ILM_PAGES_POLICY_EDIT } from '../../../../../constants'; +import { ILM_PAGES_POLICY_EDIT, INGEST_PIPELINES_EDIT } from '../../../../../constants'; import { useIlmLocator } from '../../../../../services/use_ilm_locator'; +import { useIngestPipelinesLocator } from '../../../../../services/use_ingest_pipeline_locator'; import { allowAutoCreateRadioIds } from '../../../../../../../common/constants'; import { indexModeLabels } from '../../../../../lib/index_mode_labels'; @@ -66,6 +67,13 @@ export const TabSummary: React.FunctionComponent = ({ templateDetails }) const { history, core } = useAppContext(); const ilmPolicyLink = useIlmLocator(ILM_PAGES_POLICY_EDIT, ilmPolicy?.name); + // Compute the linked ingest pipeline URL + const linkedIngestPipeline = templateDetails?.template?.settings?.index?.default_pipeline; + const linkedIngestPipelineUrl = useIngestPipelinesLocator( + INGEST_PIPELINES_EDIT, + linkedIngestPipeline + ); + return ( <> @@ -154,6 +162,25 @@ export const TabSummary: React.FunctionComponent = ({ templateDetails }) )} + + {linkedIngestPipeline && ( + <> + + + + + core.application.navigateToUrl(linkedIngestPipelineUrl)} + data-test-subj="linkedIngestPipeline" + > + {linkedIngestPipeline} + + + + )} diff --git a/x-pack/platform/plugins/shared/index_management/public/application/services/use_ingest_pipeline_locator.ts b/x-pack/platform/plugins/shared/index_management/public/application/services/use_ingest_pipeline_locator.ts new file mode 100644 index 0000000000000..cfcd9ff326f62 --- /dev/null +++ b/x-pack/platform/plugins/shared/index_management/public/application/services/use_ingest_pipeline_locator.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 { useLocatorUrl } from '@kbn/share-plugin/public'; +import { useAppContext } from '../app_context'; +import { + INGEST_PIPELINES_LOCATOR_ID, + INGEST_PIPELINES_EDIT, + INGEST_PIPELINES_LIST, +} from '../constants'; + +export const useIngestPipelinesLocator = ( + page: typeof INGEST_PIPELINES_EDIT | typeof INGEST_PIPELINES_LIST, + pipelineId?: string +): string => { + const ctx = useAppContext(); + const locator = + pipelineId === undefined ? null : ctx.url.locators.get(INGEST_PIPELINES_LOCATOR_ID)!; + const url = useLocatorUrl(locator, { page, pipelineId }, {}, [page, pipelineId]); + + return url; +}; diff --git a/x-pack/platform/plugins/shared/index_management/public/index.ts b/x-pack/platform/plugins/shared/index_management/public/index.ts index aef482471e91b..364b7a75a4c67 100644 --- a/x-pack/platform/plugins/shared/index_management/public/index.ts +++ b/x-pack/platform/plugins/shared/index_management/public/index.ts @@ -5,7 +5,6 @@ * 2.0. */ -import './index.scss'; import { PluginInitializerContext } from '@kbn/core/public'; import { IndexMgmtUIPlugin } from './plugin'; diff --git a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/add_processor_form.tsx b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/add_processor_form.tsx index 7f60ece3b2b7c..a378715bf9472 100644 --- a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/add_processor_form.tsx +++ b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/add_processor_form.tsx @@ -20,7 +20,7 @@ import { EuiFlexItem, } from '@elastic/eui'; -import { Form, FormDataProvider, FormHook } from '../../../../../shared_imports'; +import { Form, FormDataProvider, FormHook, useFormIsModified } from '../../../../../shared_imports'; import { getProcessorDescriptor } from '../shared'; import { DocumentationButton } from './documentation_button'; @@ -75,9 +75,11 @@ export const AddProcessorForm: FunctionComponent = ({ [] /* eslint-disable-line react-hooks/exhaustive-deps */ ); + const isFormDirty = useFormIsModified({ form }); + return ( - + diff --git a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/edit_processor_form.tsx b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/edit_processor_form.tsx index ff782d077156e..c6041e956ffa9 100644 --- a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/edit_processor_form.tsx +++ b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/edit_processor_form.tsx @@ -23,7 +23,7 @@ import { EuiSpacer, } from '@elastic/eui'; -import { Form, FormDataProvider, FormHook } from '../../../../../shared_imports'; +import { Form, FormDataProvider, FormHook, useFormIsModified } from '../../../../../shared_imports'; import { ProcessorInternal } from '../../types'; import { useTestPipelineContext } from '../../context'; import { getProcessorDescriptor } from '../shared'; @@ -153,6 +153,7 @@ export const EditProcessorForm: FunctionComponent = ({ flyoutContent = ; } + const isFormDirty = useFormIsModified({ form }); return ( = ({ resetProcessors(); closeFlyout(); }} + outsideClickCloses={!isFormDirty} > diff --git a/x-pack/platform/plugins/shared/lens/public/datasources/form_based/operations/definitions/ranges/ranges.test.tsx b/x-pack/platform/plugins/shared/lens/public/datasources/form_based/operations/definitions/ranges/ranges.test.tsx index a7c6e436dcfab..e85f6d6f7d550 100644 --- a/x-pack/platform/plugins/shared/lens/public/datasources/form_based/operations/definitions/ranges/ranges.test.tsx +++ b/x-pack/platform/plugins/shared/lens/public/datasources/form_based/operations/definitions/ranges/ranges.test.tsx @@ -577,45 +577,44 @@ describe('ranges', () => { /> ); - // This series of act closures are made to make it work properly the update flush - act(() => { - instance.find(EuiButtonEmpty).simulate('click'); - }); + instance.find(EuiButtonEmpty).simulate('click'); act(() => { - // need another wrapping for this in order to work instance.update(); + }); - expect(instance.find(RangePopover)).toHaveLength(2); + expect(instance.find(RangePopover)).toHaveLength(2); - // edit the range and check - instance - .find('RangePopover input[type="number"]') - .first() - .simulate('change', { - target: { - value: '50', - }, - }); + // edit the range and check + instance + .find('RangePopover input[type="number"]') + .first() + .simulate('change', { + target: { + value: '50', + }, + }); + jest.advanceTimersByTime(TYPING_DEBOUNCE_TIME * 4); - jest.advanceTimersByTime(TYPING_DEBOUNCE_TIME * 4); + act(() => { + instance.update(); + }); - expect(updateLayerSpy).toHaveBeenCalledWith({ - ...layer, - columns: { - ...layer.columns, - col1: { - ...layer.columns.col1, - params: { - ...(layer.columns.col1 as RangeIndexPatternColumn).params, - ranges: [ - { from: 0, to: DEFAULT_INTERVAL, label: '' }, - { from: 50, to: Infinity, label: '' }, - ], - }, + expect(updateLayerSpy).toHaveBeenCalledWith({ + ...layer, + columns: { + ...layer.columns, + col1: { + ...layer.columns.col1, + params: { + ...(layer.columns.col1 as RangeIndexPatternColumn).params, + ranges: [ + { from: 0, to: DEFAULT_INTERVAL, label: '' }, + { from: 50, to: Infinity, label: '' }, + ], }, }, - }); + }, }); }); @@ -632,45 +631,43 @@ describe('ranges', () => { /> ); - // This series of act closures are made to make it work properly the update flush - act(() => { - instance.find(EuiButtonEmpty).simulate('click'); - }); - + instance.find(EuiButtonEmpty).simulate('click'); act(() => { - // need another wrapping for this in order to work instance.update(); + }); + expect(instance.find(RangePopover)).toHaveLength(2); - expect(instance.find(RangePopover)).toHaveLength(2); + // edit the label and check + instance + .find('RangePopover input[type="text"]') + .first() + .simulate('change', { + target: { + value: 'customlabel', + }, + }); - // edit the label and check - instance - .find('RangePopover input[type="text"]') - .first() - .simulate('change', { - target: { - value: 'customlabel', - }, - }); + jest.advanceTimersByTime(TYPING_DEBOUNCE_TIME * 4); - jest.advanceTimersByTime(TYPING_DEBOUNCE_TIME * 4); + act(() => { + instance.update(); + }); - expect(updateLayerSpy).toHaveBeenCalledWith({ - ...layer, - columns: { - ...layer.columns, - col1: { - ...layer.columns.col1, - params: { - ...(layer.columns.col1 as RangeIndexPatternColumn).params, - ranges: [ - { from: 0, to: DEFAULT_INTERVAL, label: '' }, - { from: DEFAULT_INTERVAL, to: Infinity, label: 'customlabel' }, - ], - }, + expect(updateLayerSpy).toHaveBeenCalledWith({ + ...layer, + columns: { + ...layer.columns, + col1: { + ...layer.columns.col1, + params: { + ...(layer.columns.col1 as RangeIndexPatternColumn).params, + ranges: [ + { from: 0, to: DEFAULT_INTERVAL, label: '' }, + { from: DEFAULT_INTERVAL, to: Infinity, label: 'customlabel' }, + ], }, }, - }); + }, }); }); @@ -687,37 +684,37 @@ describe('ranges', () => { /> ); - // This series of act closures are made to make it work properly the update flush + instance.find(RangePopover).find(EuiLink).find('button').simulate('click'); act(() => { - instance.find(RangePopover).find(EuiLink).find('button').simulate('click'); + instance.update(); }); + instance + .find('RangePopover input[type="number"]') + .last() + .simulate('change', { + target: { + value: '50', + }, + }); + jest.advanceTimersByTime(TYPING_DEBOUNCE_TIME * 4); + act(() => { - // need another wrapping for this in order to work instance.update(); - instance - .find('RangePopover input[type="number"]') - .last() - .simulate('change', { - target: { - value: '50', - }, - }); - jest.advanceTimersByTime(TYPING_DEBOUNCE_TIME * 4); + }); - expect(updateLayerSpy).toHaveBeenCalledWith({ - ...layer, - columns: { - ...layer.columns, - col1: { - ...layer.columns.col1, - params: { - ...(layer.columns.col1 as RangeIndexPatternColumn).params, - ranges: [{ from: 0, to: 50, label: '' }], - }, + expect(updateLayerSpy).toHaveBeenCalledWith({ + ...layer, + columns: { + ...layer.columns, + col1: { + ...layer.columns.col1, + params: { + ...(layer.columns.col1 as RangeIndexPatternColumn).params, + ranges: [{ from: 0, to: 50, label: '' }], }, }, - }); + }, }); }); diff --git a/x-pack/platform/plugins/shared/lens/public/react_embeddable/initializers/initialize_dashboard_services.ts b/x-pack/platform/plugins/shared/lens/public/react_embeddable/initializers/initialize_dashboard_services.ts index 06e72def12c62..f88d3af2db3d9 100644 --- a/x-pack/platform/plugins/shared/lens/public/react_embeddable/initializers/initialize_dashboard_services.ts +++ b/x-pack/platform/plugins/shared/lens/public/react_embeddable/initializers/initialize_dashboard_services.ts @@ -7,7 +7,6 @@ import { noop } from 'lodash'; import { - HasInPlaceLibraryTransforms, HasLibraryTransforms, PublishesWritablePanelTitle, PublishesWritablePanelDescription, @@ -28,6 +27,7 @@ import type { IntegrationCallbacks, LensInternalApi, LensApi, + LensSerializedState, } from '../types'; import { apiHasLensComponentProps } from '../type_guards'; import { StateManagementConfig } from './initialize_state_management'; @@ -38,8 +38,7 @@ type SerializedProps = SerializedTitles & LensPanelProps & LensOverrides & LensS export interface DashboardServicesConfig { api: PublishesWritablePanelTitle & PublishesWritablePanelDescription & - HasInPlaceLibraryTransforms & - HasLibraryTransforms & + HasLibraryTransforms & Pick & Pick; serialize: () => SerializedProps; @@ -86,10 +85,10 @@ export function initializeDashboardServices( defaultPanelTitle: defaultPanelTitle$, defaultPanelDescription: defaultPanelDescription$, ...titlesApi, - libraryId$: stateConfig.api.savedObjectId, updateOverrides: internalApi.updateOverrides, getTriggerCompatibleActions: uiActions.getTriggerCompatibleActions, - // The functions below brings the HasInPlaceLibraryTransforms compliance (new interface) + + // The functions below fulfill the HasLibraryTransforms interface saveToLibrary: async (title: string) => { const { attributes } = getLatestState(); const savedObjectId = await attributeService.saveToLibrary( @@ -122,28 +121,14 @@ export function initializeDashboardServices( canLinkToLibrary: async () => !getLatestState().savedObjectId && !isTextBasedLanguage(getLatestState()), canUnlinkFromLibrary: async () => Boolean(getLatestState().savedObjectId), - unlinkFromLibrary: () => { - // broadcast the change to the main state serializer - stateConfig.api.updateSavedObjectId(undefined); - - if ((titlesApi.panelTitle.getValue() ?? '').length === 0) { - titlesApi.setPanelTitle(defaultPanelTitle$.getValue()); - } - if ((titlesApi.panelDescription.getValue() ?? '').length === 0) { - titlesApi.setPanelDescription(defaultPanelDescription$.getValue()); - } - defaultPanelTitle$.next(undefined); - defaultPanelDescription$.next(undefined); - }, - getByValueRuntimeSnapshot: (): Omit => { - const { savedObjectId, ...rest } = getLatestState(); - return rest; + getSerializedStateByReference: (newId: string) => { + const currentState = getLatestState(); + currentState.savedObjectId = newId; + return attributeService.extractReferences(currentState); }, - // The functions below brings the HasLibraryTransforms compliance (old interface) - getByReferenceState: () => getLatestState(), - getByValueState: (): Omit => { - const { savedObjectId, ...rest } = getLatestState(); - return rest; + getSerializedStateByValue: () => { + const { savedObjectId, ...byValueRuntimeState } = getLatestState(); + return attributeService.extractReferences(byValueRuntimeState); }, }, serialize: () => { diff --git a/x-pack/platform/plugins/shared/lens/public/react_embeddable/initializers/initialize_integrations.ts b/x-pack/platform/plugins/shared/lens/public/react_embeddable/initializers/initialize_integrations.ts index c3501bdfcafb9..78c90ba8c793f 100644 --- a/x-pack/platform/plugins/shared/lens/public/react_embeddable/initializers/initialize_integrations.ts +++ b/x-pack/platform/plugins/shared/lens/public/react_embeddable/initializers/initialize_integrations.ts @@ -11,7 +11,7 @@ import { isOfAggregateQueryType, } from '@kbn/es-query'; import { noop } from 'lodash'; -import type { HasSerializableState } from '@kbn/presentation-containers'; +import type { HasSerializableState } from '@kbn/presentation-publishing'; import { emptySerializer, isTextBasedLanguage } from '../helper'; import type { GetStateType, LensEmbeddableStartServices } from '../types'; import type { IntegrationCallbacks } from '../types'; diff --git a/x-pack/platform/plugins/shared/lens/public/react_embeddable/mocks/index.tsx b/x-pack/platform/plugins/shared/lens/public/react_embeddable/mocks/index.tsx index 9f88036f1c657..33f78c4fd088e 100644 --- a/x-pack/platform/plugins/shared/lens/public/react_embeddable/mocks/index.tsx +++ b/x-pack/platform/plugins/shared/lens/public/react_embeddable/mocks/index.tsx @@ -70,14 +70,12 @@ function getDefaultLensApiMock() { supportedTriggers: jest.fn(() => []), canLinkToLibrary: jest.fn(async () => false), canUnlinkFromLibrary: jest.fn(async () => false), - unlinkFromLibrary: jest.fn(), checkForDuplicateTitle: jest.fn(), /** New embeddable api inherited methods */ resetUnsavedChanges: jest.fn(), serializeState: jest.fn(), snapshotRuntimeState: jest.fn(), saveToLibrary: jest.fn(async () => 'saved-id'), - getByValueRuntimeSnapshot: jest.fn(), onEdit: jest.fn(), isEditingEnabled: jest.fn(() => true), getTypeDisplayName: jest.fn(() => 'Lens'), @@ -90,14 +88,13 @@ function getDefaultLensApiMock() { }), unsavedChanges: new BehaviorSubject(undefined), dataViews: new BehaviorSubject(undefined), - libraryId$: new BehaviorSubject(undefined), savedObjectId: new BehaviorSubject(undefined), adapters$: new BehaviorSubject({}), updateAttributes: jest.fn(), updateSavedObjectId: jest.fn(), updateOverrides: jest.fn(), - getByReferenceState: jest.fn(), - getByValueState: jest.fn(), + getSerializedStateByReference: jest.fn(), + getSerializedStateByValue: jest.fn(), getTriggerCompatibleActions: jest.fn(), blockingError: new BehaviorSubject(undefined), panelDescription: new BehaviorSubject(undefined), diff --git a/x-pack/platform/plugins/shared/lens/public/react_embeddable/types.ts b/x-pack/platform/plugins/shared/lens/public/react_embeddable/types.ts index f322f7c2b7383..990407b62dfb8 100644 --- a/x-pack/platform/plugins/shared/lens/public/react_embeddable/types.ts +++ b/x-pack/platform/plugins/shared/lens/public/react_embeddable/types.ts @@ -15,7 +15,6 @@ import type { import type { Adapters, InspectorOptions } from '@kbn/inspector-plugin/public'; import type { HasEditCapabilities, - HasInPlaceLibraryTransforms, HasLibraryTransforms, HasParentApi, HasSupportedTriggers, @@ -398,8 +397,7 @@ export type LensApi = Simplify< HasSupportedTriggers & PublishesDisabledActionIds & // Offers methods to operate from/on the linked saved object - HasInPlaceLibraryTransforms & - HasLibraryTransforms & + HasLibraryTransforms & // Let the container know the view mode PublishesViewMode & // forward the parentApi, note that will be exposed only if it satisfy the PresentationContainer interface diff --git a/x-pack/platform/plugins/shared/logs_shared/public/components/logging/log_text_stream/loading_item_view.tsx b/x-pack/platform/plugins/shared/logs_shared/public/components/logging/log_text_stream/loading_item_view.tsx index 68b21ad8d029e..e3d24b0101495 100644 --- a/x-pack/platform/plugins/shared/logs_shared/public/components/logging/log_text_stream/loading_item_view.tsx +++ b/x-pack/platform/plugins/shared/logs_shared/public/components/logging/log_text_stream/loading_item_view.tsx @@ -17,7 +17,7 @@ import { FormattedMessage, FormattedTime, FormattedRelative } from '@kbn/i18n-re import * as React from 'react'; import { Unit } from '@kbn/datemath'; -import { euiStyled } from '@kbn/kibana-react-plugin/common'; +import styled from '@emotion/styled'; import { LogTextSeparator } from './log_text_separator'; import { extendDatemath } from '../../../utils/datemath'; @@ -98,16 +98,16 @@ export class LogTextStreamLoadingItemView extends React.PureComponent< } } -const LoadingItemViewExtra = euiStyled(EuiFlexGroup)` +const LoadingItemViewExtra = styled(EuiFlexGroup)` height: 40px; `; -const ProgressEntryWrapper = euiStyled.div<{ position: Position }>` - padding-left: ${(props) => props.theme.eui.euiSizeS}; +const ProgressEntryWrapper = styled.div<{ position: Position }>` + padding-left: ${(props) => props.theme.euiTheme.size.s}; padding-top: ${(props) => - props.position === 'start' ? props.theme.eui.euiSizeL : props.theme.eui.euiSizeM}; + props.position === 'start' ? props.theme.euiTheme.size.l : props.theme.euiTheme.size.m}; padding-bottom: ${(props) => - props.position === 'end' ? props.theme.eui.euiSizeL : props.theme.eui.euiSizeM}; + props.position === 'end' ? props.theme.euiTheme.size.l : props.theme.euiTheme.size.m}; `; type ProgressMessageProps = Pick< diff --git a/x-pack/platform/plugins/shared/maps/public/react_embeddable/library_transforms.ts b/x-pack/platform/plugins/shared/maps/public/react_embeddable/library_transforms.ts index f12c1d59f4955..9c92436beef32 100644 --- a/x-pack/platform/plugins/shared/maps/public/react_embeddable/library_transforms.ts +++ b/x-pack/platform/plugins/shared/maps/public/react_embeddable/library_transforms.ts @@ -5,8 +5,7 @@ * 2.0. */ -import { SerializedPanelState } from '@kbn/presentation-containers'; -import { HasLibraryTransforms } from '@kbn/presentation-publishing'; +import { HasLibraryTransforms, SerializedPanelState } from '@kbn/presentation-publishing'; import { getCore, getCoreOverlays } from '../kibana_services'; import type { MapAttributes } from '../../common/content_management'; import { SavedMap } from '../routes/map_page'; @@ -33,7 +32,7 @@ export function getByValueState(state: MapSerializedState | undefined, attribute export function initializeLibraryTransforms( savedMap: SavedMap, serializeState: () => SerializedPanelState -): HasLibraryTransforms { +): HasLibraryTransforms { return { canLinkToLibrary: async () => { const { maps } = getCore().application.capabilities; @@ -52,8 +51,10 @@ export function initializeLibraryTransforms( }); return savedObjectId; }, - getByReferenceState: (libraryId: string) => { - return getByReferenceState(serializeState().rawState, libraryId); + getSerializedStateByReference: (libraryId: string) => { + const { rawState: initialRawState, references } = serializeState(); + const rawState = getByReferenceState(initialRawState, libraryId); + return { rawState, references }; }, checkForDuplicateTitle: async ( newTitle: string, @@ -77,8 +78,10 @@ export function initializeLibraryTransforms( canUnlinkFromLibrary: async () => { return savedMap.getSavedObjectId() !== undefined; }, - getByValueState: () => { - return getByValueState(serializeState().rawState, savedMap.getAttributes()); + getSerializedStateByValue: () => { + const { rawState: initialRawState, references } = serializeState(); + const rawState = getByValueState(initialRawState, savedMap.getAttributes()); + return { rawState, references }; }, }; } diff --git a/x-pack/platform/plugins/shared/maps/public/react_embeddable/types.ts b/x-pack/platform/plugins/shared/maps/public/react_embeddable/types.ts index a61a7e1ce6a03..45ed4a07a7398 100644 --- a/x-pack/platform/plugins/shared/maps/public/react_embeddable/types.ts +++ b/x-pack/platform/plugins/shared/maps/public/react_embeddable/types.ts @@ -35,7 +35,7 @@ import { EventHandlers } from '../reducers/non_serializable_instances'; export type MapSerializedState = SerializedTitles & Partial & { - // by-valye + // by-value attributes?: MapAttributes; // by-reference savedObjectId?: string; @@ -61,7 +61,7 @@ export type MapApi = DefaultEmbeddableApi & PublishesDataLoading & PublishesDataViews & PublishesUnifiedSearch & - HasLibraryTransforms & { + HasLibraryTransforms & { getLayerList: () => ILayer[]; reload: () => void; setEventHandlers: (eventHandlers: EventHandlers) => void; diff --git a/x-pack/platform/plugins/shared/ml/public/application/data_frame_analytics/pages/job_map/components/cytoscape.tsx b/x-pack/platform/plugins/shared/ml/public/application/data_frame_analytics/pages/job_map/components/cytoscape.tsx index 77affc598066a..55a6c5c21f85b 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/data_frame_analytics/pages/job_map/components/cytoscape.tsx +++ b/x-pack/platform/plugins/shared/ml/public/application/data_frame_analytics/pages/job_map/components/cytoscape.tsx @@ -8,7 +8,7 @@ import type { CSSProperties, PropsWithChildren } from 'react'; import React, { useState, useRef, useEffect, createContext, useCallback, useMemo } from 'react'; import { css } from '@emotion/react'; -import cytoscape, { type Stylesheet } from 'cytoscape'; +import cytoscape, { type StylesheetJson } from 'cytoscape'; // @ts-ignore no declaration file import dagre from 'cytoscape-dagre'; import { useCytoscapeOptions } from './cytoscape_options'; @@ -35,7 +35,7 @@ function useCytoscape(options: cytoscape.CytoscapeOptions) { setCy(cytoscape({ ...options, container: ref.current })); } else { // update styles for existing instance - cy.style(options.style as unknown as Stylesheet); + cy.style(options.style as StylesheetJson); } }, [options, cy]); diff --git a/x-pack/platform/plugins/shared/ml/public/application/jobs/new_job/pages/job_type/categorization_job_icon.tsx b/x-pack/platform/plugins/shared/ml/public/application/jobs/new_job/pages/job_type/categorization_job_icon.tsx deleted file mode 100644 index d1fc35e773842..0000000000000 --- a/x-pack/platform/plugins/shared/ml/public/application/jobs/new_job/pages/job_type/categorization_job_icon.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 React from 'react'; - -export const CategorizationIcon = ( - - - - -); diff --git a/x-pack/platform/plugins/shared/ml/public/application/jobs/new_job/pages/job_type/geo_job_icon.tsx b/x-pack/platform/plugins/shared/ml/public/application/jobs/new_job/pages/job_type/geo_job_icon.tsx deleted file mode 100644 index d3296b65200bf..0000000000000 --- a/x-pack/platform/plugins/shared/ml/public/application/jobs/new_job/pages/job_type/geo_job_icon.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -export const GeoIcon = ( - - - - - - - - - - - -); diff --git a/x-pack/platform/plugins/shared/ml/public/application/jobs/new_job/pages/job_type/page.tsx b/x-pack/platform/plugins/shared/ml/public/application/jobs/new_job/pages/job_type/page.tsx index 42b5623605ec0..49b61c542db30 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/jobs/new_job/pages/job_type/page.tsx +++ b/x-pack/platform/plugins/shared/ml/public/application/jobs/new_job/pages/job_type/page.tsx @@ -25,10 +25,7 @@ import { useDataSource } from '../../../../contexts/ml'; import { DataRecognizer } from '../../../../components/data_recognizer'; import { addItemToRecentlyAccessed } from '../../../../util/recently_accessed'; import { LinkCard } from '../../../../components/link_card'; -import { CategorizationIcon } from './categorization_job_icon'; import { ML_APP_LOCATOR, ML_PAGES } from '../../../../../../common/constants/locator'; -import { RareIcon } from './rare_job_icon'; -import { GeoIcon } from './geo_job_icon'; import { useCreateAndNavigateToMlLink } from '../../../../contexts/kibana/use_create_url'; import { MlPageHeader } from '../../../../components/page_header'; @@ -214,7 +211,7 @@ export const Page: FC = () => { { onClick: () => navigateToPath(`/jobs/new_job/categorization${getUrlParams()}`), icon: { - type: CategorizationIcon, + type: 'createGenericJob', ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.categorizationAriaLabel', { defaultMessage: 'Categorization job', }), @@ -230,7 +227,7 @@ export const Page: FC = () => { { onClick: () => navigateToPath(`/jobs/new_job/rare${getUrlParams()}`), icon: { - type: RareIcon, + type: 'createGenericJob', ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.rareAriaLabel', { defaultMessage: 'Rare job', }), @@ -249,7 +246,7 @@ export const Page: FC = () => { jobTypes.push({ onClick: () => navigateToPath(`/jobs/new_job/geo${getUrlParams()}`), icon: { - type: GeoIcon, + type: 'createGeoJob', ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.geoAriaLabel', { defaultMessage: 'Geo job', }), diff --git a/x-pack/platform/plugins/shared/ml/public/application/model_management/test_models/models/question_answering/question_answering_output.tsx b/x-pack/platform/plugins/shared/ml/public/application/model_management/test_models/models/question_answering/question_answering_output.tsx index 58fd02f7b5e00..96e36e9550e42 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/model_management/test_models/models/question_answering/question_answering_output.tsx +++ b/x-pack/platform/plugins/shared/ml/public/application/model_management/test_models/models/question_answering/question_answering_output.tsx @@ -60,11 +60,11 @@ function insertHighlighting(result: FormattedQuestionAnsweringResult, inputText: const ResultBadge: FC> = ({ children }) => { const { euiTheme } = useEuiTheme(); const euiFontSizeXS = useEuiFontSize('xs').fontSize; + const isAmsterdam = euiTheme.themeName === 'EUI_THEME_AMSTERDAM'; - // For Amsterdam, use a `_behindText` variant. Borealis doesn't need it because of updated contrasts. - const badgeColor = euiTheme.flags.hasVisColorAdjustment - ? // @ts-expect-error _behindText is not defined in EuiThemeComputed after Borealis update - euiTheme.colors.vis.euiColorVis5_behindText + // For Amsterdam, use a `behindText` variant. Borealis doesn't need it because of updated contrasts. + const badgeColor = isAmsterdam + ? euiTheme.colors.vis.euiColorVisBehindText5 : euiTheme.colors.vis.euiColorVis9; return ( @@ -74,9 +74,7 @@ const ResultBadge: FC> = ({ children }) => { marginRight: ICON_PADDING, marginTop: `-${ICON_PADDING}`, // For Amsterdam, add a border to the badge to improve contrast with the background. - ...(euiTheme.flags.hasVisColorAdjustment - ? { border: `1px solid ${euiTheme.colors.vis.euiColorVis5}` } - : {}), + ...(isAmsterdam ? { border: `1px solid ${euiTheme.colors.vis.euiColorVis5}` } : {}), fontSize: euiFontSizeXS, padding: '0px 6px', pointerEvents: 'none', diff --git a/x-pack/platform/plugins/shared/ml/public/application/notifications/components/notifications_list.tsx b/x-pack/platform/plugins/shared/ml/public/application/notifications/components/notifications_list.tsx index 399b880c6a331..624954fe05ce6 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/notifications/components/notifications_list.tsx +++ b/x-pack/platform/plugins/shared/ml/public/application/notifications/components/notifications_list.tsx @@ -201,9 +201,9 @@ export const NotificationsList: FC = () => { ), sortable: true, - truncateText: false, + truncateText: true, 'data-test-subj': 'mlNotificationEntity', - width: '200px', + width: '15%', }, { field: 'message', @@ -211,7 +211,9 @@ export const NotificationsList: FC = () => { ), sortable: false, - truncateText: false, + truncateText: { + lines: 8, + }, 'data-test-subj': 'mlNotificationMessage', }, ]; diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/get_dataset_info/get_relevant_field_names.ts b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/get_dataset_info/get_relevant_field_names.ts index 74d786bb6727d..d87ded0cd2c5a 100644 --- a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/get_dataset_info/get_relevant_field_names.ts +++ b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/get_dataset_info/get_relevant_field_names.ts @@ -99,6 +99,7 @@ export async function getRelevantFieldNames({ const chunkResponse$ = ( await chat('get_relevant_dataset_names', { signal, + stream: true, messages: [ { '@timestamp': new Date().toISOString(), diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/chat/route.ts b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/chat/route.ts index 5ef72dc8e7b56..1ca0eb9d1dc39 100644 --- a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/chat/route.ts +++ b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/chat/route.ts @@ -157,6 +157,7 @@ const chatRoute = createObservabilityAIAssistantServerRoute({ ); const response$ = client.chat(name, { + stream: true, messages, connectorId, signal, @@ -203,6 +204,7 @@ const chatRecallRoute = createObservabilityAIAssistantServerRoute({ client .chat(name, { ...params, + stream: true, connectorId, simulateFunctionCalling, signal, diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/knowledge_base/route.ts b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/knowledge_base/route.ts index ddc644c4b6d7c..1597d43ce52b9 100644 --- a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/knowledge_base/route.ts +++ b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/knowledge_base/route.ts @@ -14,7 +14,7 @@ import { MlDeploymentAllocationState, MlDeploymentAssignmentState, MlTrainedModelDeploymentAllocationStatus, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import moment from 'moment'; import { createObservabilityAIAssistantServerRoute } from '../create_observability_ai_assistant_server_route'; import { Instruction, KnowledgeBaseEntry, KnowledgeBaseEntryRole } from '../../../common/types'; diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/index.test.ts b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/index.test.ts index 199a6d8f1cbca..e7b1169e9c03d 100644 --- a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/index.test.ts +++ b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/index.test.ts @@ -19,7 +19,10 @@ import { MessageAddEvent, StreamingChatResponseEventType, } from '../../../common/conversation_complete'; -import { ChatCompletionEventType as InferenceChatCompletionEventType } from '@kbn/inference-common'; +import { + ChatCompletionEventType as InferenceChatCompletionEventType, + ChatCompleteResponse, +} from '@kbn/inference-common'; import { InferenceClient } from '@kbn/inference-plugin/server'; import { createFunctionResponseMessage } from '../../../common/utils/create_function_response_message'; import { CONTEXT_FUNCTION_NAME } from '../../functions/context'; @@ -88,7 +91,10 @@ function createLlmSimulator(subscriber: any) { tool_calls: msg.function_call ? [{ function: msg.function_call }] : [], }); }, - complete: async () => { + complete: async (chatCompleteResponse?: ChatCompleteResponse) => { + if (chatCompleteResponse) { + subscriber.next(chatCompleteResponse); + } subscriber.complete(); }, error: (error: Error) => { @@ -245,10 +251,25 @@ describe('Observability AI Assistant client', () => { titleLlmPromiseResolve = (title: string) => { const titleLlmSimulator = createLlmSimulator(subscriber); titleLlmSimulator - .chunk({ content: title }) - .then(() => titleLlmSimulator.next({ content: title })) - .then(() => titleLlmSimulator.tokenCount({ completion: 0, prompt: 0, total: 0 })) - .then(() => titleLlmSimulator.complete()) + .complete({ + content: '', + toolCalls: [ + { + toolCallId: 'test_id', + function: { + name: 'title_conversation', + arguments: { + title, + }, + }, + }, + ], + tokens: { + completion: 0, + prompt: 0, + total: 0, + }, + }) .catch((error) => titleLlmSimulator.error(error)); }; titleLlmPromiseReject = (error: Error) => { @@ -291,7 +312,7 @@ describe('Observability AI Assistant client', () => { expect(inferenceClientMock.chatComplete.mock.calls[0]).toEqual([ expect.objectContaining({ connectorId: 'foo', - stream: true, + stream: false, functionCalling: 'native', toolChoice: expect.objectContaining({ function: 'title_conversation', diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/index.ts b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/index.ts index 95856768c4c5d..bff57b6e75bb4 100644 --- a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/index.ts +++ b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/index.ts @@ -31,7 +31,7 @@ import { import { v4 } from 'uuid'; import type { AssistantScope } from '@kbn/ai-assistant-common'; import type { InferenceClient } from '@kbn/inference-plugin/server'; -import { ToolChoiceType } from '@kbn/inference-common'; +import { ChatCompleteResponse, FunctionCallingMode, ToolChoiceType } from '@kbn/inference-common'; import { resourceNames } from '..'; import { @@ -251,14 +251,14 @@ export class ObservabilityAIAssistantClient { getGeneratedTitle({ messages, logger: this.dependencies.logger, - chat: (name, chatParams) => { - return this.chat(name, { + chat: (name, chatParams) => + this.chat(name, { ...chatParams, simulateFunctionCalling, connectorId, signal, - }); - }, + stream: false, + }), tracer: completeTracer, }) ), @@ -294,6 +294,7 @@ export class ObservabilityAIAssistantClient { signal, simulateFunctionCalling, connectorId, + stream: true, }); }, // start out with the max number of function calls @@ -462,7 +463,7 @@ export class ObservabilityAIAssistantClient { ); }; - chat = ( + chat( name: string, { messages, @@ -472,6 +473,7 @@ export class ObservabilityAIAssistantClient { signal, simulateFunctionCalling, tracer, + stream, }: { messages: Message[]; connectorId: string; @@ -480,8 +482,11 @@ export class ObservabilityAIAssistantClient { signal: AbortSignal; simulateFunctionCalling?: boolean; tracer: LangTracer; + stream: TStream; } - ): Observable => { + ): TStream extends true + ? Observable + : Promise { let tools: Record | undefined; let toolChoice: ToolChoiceType | { function: string } | undefined; @@ -500,35 +505,44 @@ export class ObservabilityAIAssistantClient { } : ToolChoiceType.auto; } - - const chatComplete$ = defer(() => - this.dependencies.inferenceClient.chatComplete({ - connectorId, - stream: true, - messages: convertMessagesForInference( - messages.filter((message) => message.message.role !== MessageRole.System) - ), - functionCalling: simulateFunctionCalling ? 'simulated' : 'native', - toolChoice, - tools, - }) - ).pipe( - convertInferenceEventsToStreamingEvents(), - instrumentAndCountTokens(name), - failOnNonExistingFunctionCall({ functions }), - tap((event) => { - if ( - event.type === StreamingChatResponseEventType.ChatCompletionChunk && - this.dependencies.logger.isLevelEnabled('trace') - ) { - this.dependencies.logger.trace(`Received chunk: ${JSON.stringify(event.message)}`); - } - }), - shareReplay() - ); - - return chatComplete$; - }; + const options = { + connectorId, + messages: convertMessagesForInference( + messages.filter((message) => message.message.role !== MessageRole.System) + ), + toolChoice, + tools, + functionCalling: (simulateFunctionCalling ? 'simulated' : 'native') as FunctionCallingMode, + }; + if (stream) { + return defer(() => + this.dependencies.inferenceClient.chatComplete({ + ...options, + stream: true, + }) + ).pipe( + convertInferenceEventsToStreamingEvents(), + instrumentAndCountTokens(name), + failOnNonExistingFunctionCall({ functions }), + tap((event) => { + if ( + event.type === StreamingChatResponseEventType.ChatCompletionChunk && + this.dependencies.logger.isLevelEnabled('trace') + ) { + this.dependencies.logger.trace(`Received chunk: ${JSON.stringify(event.message)}`); + } + }), + shareReplay() + ) as TStream extends true + ? Observable + : never; + } else { + return this.dependencies.inferenceClient.chatComplete({ + ...options, + stream: false, + }) as TStream extends true ? never : Promise; + } + } find = async (options?: { query?: string }): Promise<{ conversations: Conversation[] }> => { const response = await this.dependencies.esClient.asInternalUser.search({ diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/continue_conversation.ts b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/continue_conversation.ts index 4c55d32362878..b34517b07722d 100644 --- a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/continue_conversation.ts +++ b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/continue_conversation.ts @@ -243,6 +243,7 @@ export function continueConversation({ functions: definitions, tracer, connectorId, + stream: true, }).pipe(emitWithConcatenatedMessage(), catchFunctionNotFoundError(functionLimitExceeded)); } diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/extract_token_count.ts b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/extract_token_count.ts index 0d11db24732f3..cf4719ad75b8e 100644 --- a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/extract_token_count.ts +++ b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/extract_token_count.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { filter, OperatorFunction, scan } from 'rxjs'; +import { filter, OperatorFunction, scan, startWith } from 'rxjs'; import { StreamingChatResponseEvent, StreamingChatResponseEventType, @@ -30,7 +30,8 @@ export function extractTokenCount(): OperatorFunction< return acc; }, { completion: 0, prompt: 0, total: 0 } - ) + ), + startWith({ completion: 0, prompt: 0, total: 0 }) ); }; } diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.test.ts b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.test.ts index a8ddd5233132a..42453f8d407b6 100644 --- a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.test.ts +++ b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.test.ts @@ -5,13 +5,8 @@ * 2.0. */ import { filter, lastValueFrom, of, throwError, toArray } from 'rxjs'; -import { - ChatCompletionChunkEvent, - Message, - MessageRole, - StreamingChatResponseEventType, -} from '../../../../common'; -import { ChatEvent } from '../../../../common/conversation_complete'; +import { ChatCompleteResponse } from '@kbn/inference-common'; +import { Message, MessageRole, StreamingChatResponseEventType } from '../../../../common'; import { LangTracer } from '../instrumentation/lang_tracer'; import { TITLE_CONVERSATION_FUNCTION_NAME, getGeneratedTitle } from './get_generated_title'; @@ -26,19 +21,27 @@ describe('getGeneratedTitle', () => { }, ]; - function createChatCompletionChunk( - content: string | { content?: string; function_call?: { name: string; arguments: string } } - ): ChatCompletionChunkEvent { - const msg = typeof content === 'string' ? { content } : content; - + function createChatCompletionResponse(content: { + content?: string; + function_call?: { name: string; arguments: { [key: string]: string } }; + }): ChatCompleteResponse { return { - type: StreamingChatResponseEventType.ChatCompletionChunk, - id: 'id', - message: msg, + content: content.content || '', + toolCalls: content.function_call + ? [ + { + toolCallId: 'test_id', + function: { + name: content.function_call?.name, + arguments: content.function_call?.arguments, + }, + }, + ] + : [], }; } - function callGenerateTitle(...rest: [ChatEvent[]] | [{}, ChatEvent[]]) { + function callGenerateTitle(...rest: [ChatCompleteResponse[]] | [{}, ChatCompleteResponse[]]) { const options = rest.length === 1 ? {} : rest[0]; const chunks = rest.length === 1 ? rest[0] : rest[1]; @@ -62,10 +65,10 @@ describe('getGeneratedTitle', () => { it('returns the given title as a string', async () => { const { title$ } = callGenerateTitle([ - createChatCompletionChunk({ + createChatCompletionResponse({ function_call: { name: 'title_conversation', - arguments: JSON.stringify({ title: 'My title' }), + arguments: { title: 'My title' }, }, }), ]); @@ -76,13 +79,12 @@ describe('getGeneratedTitle', () => { expect(title).toEqual('My title'); }); - it('calls chat with the user message', async () => { const { chatSpy, title$ } = callGenerateTitle([ - createChatCompletionChunk({ + createChatCompletionResponse({ function_call: { name: TITLE_CONVERSATION_FUNCTION_NAME, - arguments: JSON.stringify({ title: 'My title' }), + arguments: { title: 'My title' }, }, }), ]); @@ -99,10 +101,10 @@ describe('getGeneratedTitle', () => { it('strips quotes from the title', async () => { async function testTitle(title: string) { const { title$ } = callGenerateTitle([ - createChatCompletionChunk({ + createChatCompletionResponse({ function_call: { name: 'title_conversation', - arguments: JSON.stringify({ title }), + arguments: { title }, }, }), ]); @@ -117,37 +119,21 @@ describe('getGeneratedTitle', () => { expect(await testTitle(`"User's request for a title"`)).toEqual(`User's request for a title`); }); - it('handles partial updates', async () => { - const { title$ } = callGenerateTitle([ - createChatCompletionChunk({ - function_call: { - name: 'title_conversation', - arguments: '', - }, - }), - createChatCompletionChunk({ - function_call: { - name: '', - arguments: JSON.stringify({ title: 'My title' }), - }, - }), - ]); - - const title = await lastValueFrom(title$); - - expect(title).toEqual('My title'); - }); - it('ignores token count events and still passes them through', async () => { const { title$ } = callGenerateTitle([ - createChatCompletionChunk({ - function_call: { - name: 'title_conversation', - arguments: JSON.stringify({ title: 'My title' }), - }, - }), { - type: StreamingChatResponseEventType.TokenCount, + content: '', + toolCalls: [ + { + toolCallId: 'test_id', + function: { + name: 'title_conversation', + arguments: { + title: 'My title', + }, + }, + }, + ], tokens: { completion: 10, prompt: 10, diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.ts b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.ts index 79dac3c036046..3f1b9f43cd35f 100644 --- a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.ts +++ b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.ts @@ -5,13 +5,12 @@ * 2.0. */ -import { catchError, last, map, Observable, of, tap } from 'rxjs'; +import { catchError, mergeMap, Observable, of, tap, from } from 'rxjs'; import { Logger } from '@kbn/logging'; +import { ChatCompleteResponse } from '@kbn/inference-common'; import type { ObservabilityAIAssistantClient } from '..'; -import { Message, MessageRole } from '../../../../common'; -import { concatenateChatCompletionChunks } from '../../../../common/utils/concatenate_chat_completion_chunks'; -import { hideTokenCountEvents } from './hide_token_count_events'; -import { ChatEvent, TokenCountEvent } from '../../../../common/conversation_complete'; +import { Message, MessageRole, StreamingChatResponseEventType } from '../../../../common'; +import { TokenCountEvent } from '../../../../common/conversation_complete'; import { LangTracer } from '../instrumentation/lang_tracer'; export const TITLE_CONVERSATION_FUNCTION_NAME = 'title_conversation'; @@ -22,7 +21,7 @@ type ChatFunctionWithoutConnectorAndTokenCount = ( Parameters[1], 'connectorId' | 'signal' | 'simulateFunctionCalling' > -) => Observable; +) => Promise; export function getGeneratedTitle({ messages, @@ -35,7 +34,7 @@ export function getGeneratedTitle({ logger: Pick; tracer: LangTracer; }): Observable { - return hideTokenCountEvents((hide) => + return from( chat('generate_title', { messages: [ { @@ -75,32 +74,44 @@ export function getGeneratedTitle({ ], functionCall: TITLE_CONVERSATION_FUNCTION_NAME, tracer, - }).pipe( - hide(), - concatenateChatCompletionChunks(), - last(), - map((concatenatedMessage) => { - const title: string = - (concatenatedMessage.message.function_call.name - ? JSON.parse(concatenatedMessage.message.function_call.arguments).title - : concatenatedMessage.message?.content) || ''; + stream: false, + }) + ).pipe( + mergeMap((response) => { + let title: string = + (response.toolCalls[0].function.name + ? (response.toolCalls[0].function.arguments as { title: string }).title + : response.content) || ''; - // This captures a string enclosed in single or double quotes. - // It extracts the string content without the quotes. - // Example matches: - // - "Hello, World!" => Captures: Hello, World! - // - 'Another Example' => Captures: Another Example - // - JustTextWithoutQuotes => Captures: JustTextWithoutQuotes + // This captures a string enclosed in single or double quotes. + // It extracts the string content without the quotes. + // Example matches: + // - "Hello, World!" => Captures: Hello, World! + // - 'Another Example' => Captures: Another Example + // - JustTextWithoutQuotes => Captures: JustTextWithoutQuotes + title = title.replace(/^"(.*)"$/g, '$1').replace(/^'(.*)'$/g, '$1'); - return title.replace(/^"(.*)"$/g, '$1').replace(/^'(.*)'$/g, '$1'); - }), - tap((event) => { - if (typeof event === 'string') { - logger.debug(`Generated title: ${event}`); - } - }) - ) - ).pipe( + const tokenCount: TokenCountEvent | undefined = response.tokens + ? { + type: StreamingChatResponseEventType.TokenCount, + tokens: { + completion: response.tokens.completion, + prompt: response.tokens.prompt, + total: response.tokens.total, + }, + } + : undefined; + + const events: Array = [title]; + if (tokenCount) events.push(tokenCount); + + return from(events); // Emit each event separately + }), + tap((event) => { + if (typeof event === 'string') { + logger.debug(`Generated title: ${event}`); + } + }), catchError((error) => { logger.error(`Error generating title`); logger.error(error); diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/conversation_component_template.ts b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/conversation_component_template.ts index 5a8ad441b8e54..435b2a731fa9b 100644 --- a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/conversation_component_template.ts +++ b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/conversation_component_template.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ClusterComponentTemplate } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { ClusterComponentTemplate } from '@elastic/elasticsearch/lib/api/types'; const keyword = { type: 'keyword' as const, diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/kb_component_template.ts b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/kb_component_template.ts index 49e856db29d50..9307aa8443497 100644 --- a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/kb_component_template.ts +++ b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/kb_component_template.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ClusterComponentTemplate } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { ClusterComponentTemplate } from '@elastic/elasticsearch/lib/api/types'; import { AI_ASSISTANT_KB_INFERENCE_ID } from './inference_endpoint'; const keyword = { diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/knowledge_base_service/index.ts b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/knowledge_base_service/index.ts index cba83f715ff61..a73be984920c4 100644 --- a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/knowledge_base_service/index.ts +++ b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/knowledge_base_service/index.ts @@ -17,7 +17,7 @@ import { KnowledgeBaseEntryRole, KnowledgeBaseType, } from '../../../common/types'; -import { getAccessQuery } from '../util/get_access_query'; +import { getAccessQuery, getUserAccessFilters } from '../util/get_access_query'; import { getCategoryQuery } from '../util/get_category_query'; import { createInferenceEndpoint, @@ -342,7 +342,13 @@ export class KnowledgeBaseService { filter: [ { term: { type: KnowledgeBaseType.UserInstruction } }, { term: { public: isPublic } }, - ...getAccessQuery({ user, namespace }), + { term: { namespace } }, + { + bool: { + should: [...getUserAccessFilters(user)], + minimum_should_match: 1, + }, + }, ], }, }, @@ -393,7 +399,7 @@ export class KnowledgeBaseService { }: { entry: Omit; user?: { name: string; id?: string }; - namespace?: string; + namespace: string; }): Promise => { if (!this.dependencies.config.enableKnowledgeBase) { return; diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/get_access_query.ts b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/get_access_query.ts index b517273630f56..1788e23bed95c 100644 --- a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/get_access_query.ts +++ b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/get_access_query.ts @@ -25,9 +25,7 @@ export function getAccessQuery({ bool: { should: [ { - term: { - namespace, - }, + term: { namespace }, }, { bool: { @@ -47,7 +45,7 @@ export function getAccessQuery({ ]; } -function getUserAccessFilters(user?: { name: string; id?: string }) { +export function getUserAccessFilters(user?: { name: string; id?: string }) { if (!user) { return []; } diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/utils/recall/score_suggestions.ts b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/utils/recall/score_suggestions.ts index b57e5928ce0ba..9993e4e66fb3f 100644 --- a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/utils/recall/score_suggestions.ts +++ b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/utils/recall/score_suggestions.ts @@ -112,6 +112,7 @@ export async function scoreSuggestions({ functions: [scoreFunction], functionCall: 'score', signal, + stream: true, }).pipe(concatenateChatCompletionChunks()) ); diff --git a/x-pack/platform/plugins/shared/rule_registry/server/rule_data_plugin_service/resource_installer.ts b/x-pack/platform/plugins/shared/rule_registry/server/rule_data_plugin_service/resource_installer.ts index 2a6533d7e1002..59c9928d5358b 100644 --- a/x-pack/platform/plugins/shared/rule_registry/server/rule_data_plugin_service/resource_installer.ts +++ b/x-pack/platform/plugins/shared/rule_registry/server/rule_data_plugin_service/resource_installer.ts @@ -93,8 +93,8 @@ export class ResourceInstaller { logger, esClient: clusterClient, template: { + ...ecsComponentTemplate, name: ECS_COMPONENT_TEMPLATE_NAME, - body: ecsComponentTemplate, }, totalFieldsLimit: TOTAL_FIELDS_LIMIT, }), @@ -103,8 +103,8 @@ export class ResourceInstaller { logger, esClient: clusterClient, template: { + ...technicalComponentTemplate, name: TECHNICAL_COMPONENT_TEMPLATE_NAME, - body: technicalComponentTemplate, }, totalFieldsLimit: TOTAL_FIELDS_LIMIT, }), @@ -168,13 +168,11 @@ export class ResourceInstaller { esClient: clusterClient, template: { name: indexInfo.getComponentTemplateName(ct.name), - body: { - template: { - settings: ct.settings ?? {}, - mappings: ct.mappings, - }, - _meta: ct._meta, + template: { + settings: ct.settings ?? {}, + mappings: ct.mappings, }, + _meta: ct._meta, }, totalFieldsLimit: TOTAL_FIELDS_LIMIT, }); diff --git a/x-pack/platform/plugins/shared/stack_alerts/common/build_sorted_events_query.ts b/x-pack/platform/plugins/shared/stack_alerts/common/build_sorted_events_query.ts index 5253fb8eb74ee..fe8ab382f10d9 100644 --- a/x-pack/platform/plugins/shared/stack_alerts/common/build_sorted_events_query.ts +++ b/x-pack/platform/plugins/shared/stack_alerts/common/build_sorted_events_query.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import type { ESSearchRequest } from '@kbn/es-types'; interface BuildSortedEventsQueryOpts { diff --git a/x-pack/platform/plugins/shared/stack_alerts/server/rule_types/es_query/action_context.ts b/x-pack/platform/plugins/shared/stack_alerts/server/rule_types/es_query/action_context.ts index e950cc26380a5..1a22eb71d33b8 100644 --- a/x-pack/platform/plugins/shared/stack_alerts/server/rule_types/es_query/action_context.ts +++ b/x-pack/platform/plugins/shared/stack_alerts/server/rule_types/es_query/action_context.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { AlertInstanceContext } from '@kbn/alerting-plugin/server'; import { EsQueryRuleParams } from './rule_type_params'; import { Comparator } from '../../../common/comparator_types'; diff --git a/x-pack/platform/plugins/shared/stack_alerts/server/rule_types/es_query/util.ts b/x-pack/platform/plugins/shared/stack_alerts/server/rule_types/es_query/util.ts index 26994006ead11..98f7894d85fd4 100644 --- a/x-pack/platform/plugins/shared/stack_alerts/server/rule_types/es_query/util.ts +++ b/x-pack/platform/plugins/shared/stack_alerts/server/rule_types/es_query/util.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import { SearchResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { OnlyEsQueryRuleParams } from './types'; import { EsQueryRuleParams } from './rule_type_params'; diff --git a/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/es_index/index.test.ts b/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/es_index/index.test.ts index 5b7353ef58291..7444168c54f3d 100644 --- a/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/es_index/index.test.ts +++ b/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/es_index/index.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { validateConfig, validateParams } from '@kbn/actions-plugin/server/lib'; import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; @@ -202,24 +202,24 @@ describe('execute()', () => { }); expect(scopedClusterClient.bulk.mock.calls).toMatchInlineSnapshot(` - Array [ - Array [ + Array [ + Array [ + Object { + "index": "index-value", + "operations": Array [ Object { - "body": Array [ - Object { - "index": Object { - "op_type": "create", - }, - }, - Object { - "jim": "bob", - }, - ], - "index": "index-value", - "refresh": false, + "index": Object { + "op_type": "create", + }, + }, + Object { + "jim": "bob", }, ], - ] + "refresh": false, + }, + ], + ] `); // full params @@ -247,30 +247,30 @@ describe('execute()', () => { const calls = scopedClusterClient.bulk.mock.calls; const timeValue = ( - ((calls[0][0] as estypes.BulkRequest)?.body as unknown[])[1] as Record + (calls[0][0] as estypes.BulkRequest)?.operations?.[1] as Record ).field_to_use_for_time; expect(timeValue).toBeInstanceOf(Date); - delete (((calls[0][0] as estypes.BulkRequest)?.body as unknown[])[1] as Record) + delete ((calls[0][0] as estypes.BulkRequest)?.operations?.[1] as Record) .field_to_use_for_time; expect(calls).toMatchInlineSnapshot(` + Array [ Array [ - Array [ - Object { - "body": Array [ - Object { - "index": Object { - "op_type": "create", - }, - }, - Object { - "jimbob": "jr", + Object { + "index": "index-value", + "operations": Array [ + Object { + "index": Object { + "op_type": "create", }, - ], - "index": "index-value", - "refresh": true, - }, - ], - ] + }, + Object { + "jimbob": "jr", + }, + ], + "refresh": true, + }, + ], + ] `); // minimal params @@ -301,7 +301,8 @@ describe('execute()', () => { Array [ Array [ Object { - "body": Array [ + "index": "index-value", + "operations": Array [ Object { "index": Object { "op_type": "create", @@ -311,7 +312,6 @@ describe('execute()', () => { "jim": "bob", }, ], - "index": "index-value", "refresh": false, }, ], @@ -342,32 +342,32 @@ describe('execute()', () => { }); expect(scopedClusterClient.bulk.mock.calls).toMatchInlineSnapshot(` - Array [ - Array [ + Array [ + Array [ + Object { + "index": "index-value", + "operations": Array [ Object { - "body": Array [ - Object { - "index": Object { - "op_type": "create", - }, - }, - Object { - "a": 1, - }, - Object { - "index": Object { - "op_type": "create", - }, - }, - Object { - "b": 2, - }, - ], - "index": "index-value", - "refresh": false, + "index": Object { + "op_type": "create", + }, + }, + Object { + "a": 1, + }, + Object { + "index": Object { + "op_type": "create", + }, + }, + Object { + "b": 2, }, ], - ] + "refresh": false, + }, + ], + ] `); }); diff --git a/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/es_index/index.ts b/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/es_index/index.ts index 915a66568c20e..b86ed0fcc22f6 100644 --- a/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/es_index/index.ts +++ b/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/es_index/index.ts @@ -25,10 +25,7 @@ import { ALERT_HISTORY_PREFIX, buildAlertHistoryDocument, } from '@kbn/actions-plugin/common'; -import { - BulkOperationType, - BulkResponseItem, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { BulkOperationType, BulkResponseItem } from '@elastic/elasticsearch/lib/api/types'; export type ESIndexConnectorType = ConnectorType< ConnectorTypeConfigType, @@ -108,20 +105,20 @@ async function executor( const { actionId, config, params, services, logger } = execOptions; const index = params.indexOverride || config.index; - const bulkBody = []; + const operations = []; for (const document of params.documents) { const timeField = config.executionTimeField == null ? '' : config.executionTimeField.trim(); if (timeField !== '') { document[timeField] = new Date(); } - bulkBody.push({ index: { op_type: 'create' } }); - bulkBody.push(document); + operations.push({ index: { op_type: 'create' } }); + operations.push(document); } const bulkParams = { index, - body: bulkBody, + operations, refresh: config.refresh, }; diff --git a/x-pack/platform/plugins/shared/task_manager/server/lib/bulk_operation_buffer.ts b/x-pack/platform/plugins/shared/task_manager/server/lib/bulk_operation_buffer.ts index 76a7fe338a7e5..4a2f0b96b2e3a 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/lib/bulk_operation_buffer.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/lib/bulk_operation_buffer.ts @@ -7,7 +7,7 @@ import { Logger } from '@kbn/core/server'; import { map } from 'lodash'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { Subject, race, from } from 'rxjs'; import { bufferWhen, filter, bufferCount, flatMap, mapTo, first } from 'rxjs'; import { SavedObjectError } from '@kbn/core-saved-objects-common'; diff --git a/x-pack/platform/plugins/shared/task_manager/server/metrics/task_metrics_collector.ts b/x-pack/platform/plugins/shared/task_manager/server/metrics/task_metrics_collector.ts index 75b8a8beec5e8..4b064d013d2ef 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/metrics/task_metrics_collector.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/metrics/task_metrics_collector.ts @@ -10,7 +10,7 @@ import { AggregationsStringTermsBucket, AggregationsStringTermsBucketKeys, AggregationsTermsAggregateBase, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import { Observable, Subject } from 'rxjs'; import { TaskStore } from '../task_store'; import { diff --git a/x-pack/platform/plugins/shared/task_manager/server/monitoring/workload_statistics.test.ts b/x-pack/platform/plugins/shared/task_manager/server/monitoring/workload_statistics.test.ts index 0326e07de6f48..b4f4d4c8d3f18 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/monitoring/workload_statistics.test.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/monitoring/workload_statistics.test.ts @@ -21,7 +21,7 @@ import { times } from 'lodash'; import { taskStoreMock } from '../task_store.mock'; import { of, Subject } from 'rxjs'; import { sleep } from '../test_utils'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { TaskTypeDictionary } from '../task_type_dictionary'; type ResponseWithAggs = Omit, 'aggregations'> & { diff --git a/x-pack/platform/plugins/shared/task_manager/server/monitoring/workload_statistics.ts b/x-pack/platform/plugins/shared/task_manager/server/monitoring/workload_statistics.ts index 37f1291132547..46a372d4cf328 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/monitoring/workload_statistics.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/monitoring/workload_statistics.ts @@ -10,7 +10,7 @@ import { mergeMap, map, filter, switchMap, catchError } from 'rxjs'; import { Logger } from '@kbn/core/server'; import { JsonObject } from '@kbn/utility-types'; import { keyBy, mapValues } from 'lodash'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import type { AggregationResultOf } from '@kbn/es-types'; import { AggregatedStatProvider } from '../lib/runtime_statistics_aggregator'; import { parseIntervalAsSecond, asInterval, parseIntervalAsMillisecond } from '../lib/intervals'; diff --git a/x-pack/platform/plugins/shared/task_manager/server/plugin.ts b/x-pack/platform/plugins/shared/task_manager/server/plugin.ts index e8ed5aefbe6f9..d30df4eed331e 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/plugin.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/plugin.ts @@ -7,7 +7,7 @@ import { combineLatest, Observable, Subject, BehaviorSubject } from 'rxjs'; import { map, distinctUntilChanged } from 'rxjs'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import type { UsageCollectionSetup, UsageCollectionStart, diff --git a/x-pack/platform/plugins/shared/task_manager/server/queries/aggregate_task_overdue_percentiles_for_type.ts b/x-pack/platform/plugins/shared/task_manager/server/queries/aggregate_task_overdue_percentiles_for_type.ts index 67b28ce600e3a..dbeff5ea943a9 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/queries/aggregate_task_overdue_percentiles_for_type.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/queries/aggregate_task_overdue_percentiles_for_type.ts @@ -9,7 +9,7 @@ import type { AggregationsAggregationContainer, QueryDslQueryContainer, MappingRuntimeFields, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import { IdleTaskWithExpiredRunAt, RunningOrClaimingTaskWithExpiredRetryAt, diff --git a/x-pack/platform/plugins/shared/task_manager/server/queries/mark_available_tasks_as_claimed.ts b/x-pack/platform/plugins/shared/task_manager/server/queries/mark_available_tasks_as_claimed.ts index ec99c6ad5bf80..9a75f5e9f10c8 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/queries/mark_available_tasks_as_claimed.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/queries/mark_available_tasks_as_claimed.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { TaskTypeDictionary } from '../task_type_dictionary'; import { TaskStatus, TaskPriority, ConcreteTaskInstance } from '../task'; import { @@ -128,7 +128,9 @@ function getSortByPriority(definitions: TaskTypeDictionary): estypes.SortCombina // TODO: we could do this locally as well, but they may starve source: ` String taskType = doc['task.taskType'].value; - if (params.priority_map.containsKey(taskType)) { + if (doc['task.priority'].size() != 0) { + return doc['task.priority'].value; + } else if (params.priority_map.containsKey(taskType)) { return params.priority_map[taskType]; } else { return ${TaskPriority.Normal}; diff --git a/x-pack/platform/plugins/shared/task_manager/server/queries/query_clauses.ts b/x-pack/platform/plugins/shared/task_manager/server/queries/query_clauses.ts index 140ae0659d329..9f28e0a8f7575 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/queries/query_clauses.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/queries/query_clauses.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; export interface MustCondition { bool: Pick; diff --git a/x-pack/platform/plugins/shared/task_manager/server/removed_tasks/mark_removed_tasks_as_unrecognized.test.ts b/x-pack/platform/plugins/shared/task_manager/server/removed_tasks/mark_removed_tasks_as_unrecognized.test.ts index 1485216a67f33..1d60c926d212b 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/removed_tasks/mark_removed_tasks_as_unrecognized.test.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/removed_tasks/mark_removed_tasks_as_unrecognized.test.ts @@ -8,7 +8,7 @@ import { mockLogger } from '../test_utils'; import { coreMock, elasticsearchServiceMock } from '@kbn/core/server/mocks'; import { SCHEDULE_INTERVAL, taskRunner } from './mark_removed_tasks_as_unrecognized'; -import { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { SearchHit } from '@elastic/elasticsearch/lib/api/types'; const createTaskDoc = (id: string = '1'): SearchHit => ({ _index: '.kibana_task_manager_9.0.0_001', diff --git a/x-pack/platform/plugins/shared/task_manager/server/removed_tasks/mark_removed_tasks_as_unrecognized.ts b/x-pack/platform/plugins/shared/task_manager/server/removed_tasks/mark_removed_tasks_as_unrecognized.ts index a0b518849d909..b21ac92a73307 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/removed_tasks/mark_removed_tasks_as_unrecognized.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/removed_tasks/mark_removed_tasks_as_unrecognized.ts @@ -8,7 +8,7 @@ import { Logger } from '@kbn/logging'; import { CoreStart } from '@kbn/core-lifecycle-server'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; -import { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { SearchHit } from '@elastic/elasticsearch/lib/api/types'; import { TaskScheduling } from '../task_scheduling'; import { TaskTypeDictionary } from '../task_type_dictionary'; import { ConcreteTaskInstance, TaskManagerStartContract } from '..'; diff --git a/x-pack/platform/plugins/shared/task_manager/server/routes/background_task_utilization.test.ts b/x-pack/platform/plugins/shared/task_manager/server/routes/background_task_utilization.test.ts index 322060b4f9b61..bb8585412382d 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/routes/background_task_utilization.test.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/routes/background_task_utilization.test.ts @@ -15,7 +15,7 @@ import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/us import { MonitoringStats } from '../monitoring'; import { configSchema, TaskManagerConfig } from '../config'; import { backgroundTaskUtilizationRoute } from './background_task_utilization'; -import { SecurityHasPrivilegesResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { SecurityHasPrivilegesResponse } from '@elastic/elasticsearch/lib/api/types'; const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); diff --git a/x-pack/platform/plugins/shared/task_manager/server/saved_objects/index.ts b/x-pack/platform/plugins/shared/task_manager/server/saved_objects/index.ts index dc1cd97677767..bd82eacc3260c 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/saved_objects/index.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/saved_objects/index.ts @@ -6,7 +6,7 @@ */ import type { SavedObjectsServiceSetup } from '@kbn/core/server'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { backgroundTaskNodeMapping, taskMappings } from './mappings'; import { getMigrations } from './migrations'; import { TaskManagerConfig } from '../config'; diff --git a/x-pack/platform/plugins/shared/task_manager/server/task.ts b/x-pack/platform/plugins/shared/task_manager/server/task.ts index c52e9dfc52221..78cbea8cd0345 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/task.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/task.ts @@ -351,6 +351,11 @@ export interface TaskInstance { * Used to break up tasks so each Kibana node can claim tasks on a subset of the partitions */ partition?: number; + + /* + * Optionally override the priority defined in the task type for this specific task instance + */ + priority?: TaskPriority; } /** diff --git a/x-pack/platform/plugins/shared/task_manager/server/task_claimers/strategy_update_by_query.test.ts b/x-pack/platform/plugins/shared/task_manager/server/task_claimers/strategy_update_by_query.test.ts index 2731dfed240a4..967fc4a9fce2e 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/task_claimers/strategy_update_by_query.test.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/task_claimers/strategy_update_by_query.test.ts @@ -356,7 +356,9 @@ describe('TaskClaiming', () => { }, source: ` String taskType = doc['task.taskType'].value; - if (params.priority_map.containsKey(taskType)) { + if (doc['task.priority'].size() != 0) { + return doc['task.priority'].value; + } else if (params.priority_map.containsKey(taskType)) { return params.priority_map[taskType]; } else { return 50; diff --git a/x-pack/platform/plugins/shared/task_manager/server/task_store.test.ts b/x-pack/platform/plugins/shared/task_manager/server/task_store.test.ts index a195baeb893ac..7837d01b115cf 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/task_store.test.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/task_store.test.ts @@ -7,7 +7,7 @@ import { schema } from '@kbn/config-schema'; import { Client } from '@elastic/elasticsearch'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import _ from 'lodash'; import { first } from 'rxjs'; diff --git a/x-pack/platform/plugins/shared/task_manager/server/task_store.ts b/x-pack/platform/plugins/shared/task_manager/server/task_store.ts index 6c48f3bd7552d..ddaef89d1cdf1 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/task_store.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/task_store.ts @@ -14,7 +14,7 @@ import { Subject } from 'rxjs'; import { omit, defaults, get } from 'lodash'; import { SavedObjectError } from '@kbn/core-saved-objects-common'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import type { SavedObjectsBulkDeleteResponse, Logger } from '@kbn/core/server'; import { diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/common/data/lib/build_agg.ts b/x-pack/platform/plugins/shared/triggers_actions_ui/common/data/lib/build_agg.ts index 0a5bc5cc97fe2..22d95c86a1ff1 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/common/data/lib/build_agg.ts +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/common/data/lib/build_agg.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { AggregationsAggregationContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { AggregationsAggregationContainer } from '@elastic/elasticsearch/lib/api/types'; import { DateRangeInfo, getDateRangeInfo } from './date_range_info'; export interface BuildAggregationOpts { diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/common/data/lib/parse_aggregation_results.ts b/x-pack/platform/plugins/shared/triggers_actions_ui/common/data/lib/parse_aggregation_results.ts index d1f65d0e7b360..0a7236d3867a6 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/common/data/lib/parse_aggregation_results.ts +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/common/data/lib/parse_aggregation_results.ts @@ -10,7 +10,7 @@ import { SearchHit, SearchHitsMetadata, AggregationsSingleMetricAggregateBase, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import type { Group } from '@kbn/observability-alerting-rule-utils'; export const UngroupedGroupId = 'all documents'; diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/lib/action_connector_api/load_execution_log_aggregations.ts b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/lib/action_connector_api/load_execution_log_aggregations.ts index 76a96fe300359..7d22ae8080cef 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/lib/action_connector_api/load_execution_log_aggregations.ts +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/lib/action_connector_api/load_execution_log_aggregations.ts @@ -8,7 +8,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { HttpSetup } from '@kbn/core/public'; -import type { SortOrder } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { SortOrder } from '@elastic/elasticsearch/lib/api/types'; import { IExecutionLog, ExecutionLogSortFields, diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/lib/rule_api/load_action_error_log.ts b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/lib/rule_api/load_action_error_log.ts index 7bfef44335a4c..3cd0f0cd56a35 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/lib/rule_api/load_action_error_log.ts +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/lib/rule_api/load_action_error_log.ts @@ -6,7 +6,7 @@ */ import { HttpSetup } from '@kbn/core/public'; -import type { SortOrder } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { SortOrder } from '@elastic/elasticsearch/lib/api/types'; import { IExecutionErrorsResult, ActionErrorLogSortFields } from '@kbn/alerting-plugin/common'; import { INTERNAL_BASE_ALERTING_API_PATH } from '../../constants'; import { getFilter } from './get_filter'; diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/lib/rule_api/load_execution_log_aggregations.ts b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/lib/rule_api/load_execution_log_aggregations.ts index 334b4aea135a2..ffd01a0adcecc 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/lib/rule_api/load_execution_log_aggregations.ts +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/lib/rule_api/load_execution_log_aggregations.ts @@ -8,7 +8,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { HttpSetup } from '@kbn/core/public'; -import type { SortOrder } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { SortOrder } from '@elastic/elasticsearch/lib/api/types'; import { IExecutionLog, ExecutionLogSortFields, diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.test.tsx b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.test.tsx index 945ab23c43611..1e795a2cf3dd8 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.test.tsx +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.test.tsx @@ -381,7 +381,7 @@ describe('action_type_form', () => { jest.useFakeTimers({ legacyFakeTimers: true }); wrapper.find('[data-test-subj="action-group-error-icon"]').first().simulate('mouseOver'); // Run the timers so the EuiTooltip will be visible - jest.runAllTimers(); + jest.runOnlyPendingTimers(); wrapper.update(); expect(wrapper.find('.euiToolTipPopover').last().text()).toBe('Action contains errors.'); // Clearing all mocks will also reset fake timers. diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx index 93bb4f18dfe9a..e569b15b681ff 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx @@ -19,7 +19,7 @@ import { EuiCopy, EuiDataGridControlColumn, } from '@elastic/eui'; -import type { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/types'; import { ALERT_CASE_IDS, ALERT_MAINTENANCE_WINDOW_IDS } from '@kbn/rule-data-utils'; import type { RuleRegistrySearchRequestPagination } from '@kbn/rule-registry-plugin/common'; import type { BrowserFields } from '@kbn/alerting-types'; @@ -27,7 +27,7 @@ import { Storage } from '@kbn/kibana-utils-plugin/public'; import type { QueryDslQueryContainer, SortCombinations, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +} from '@elastic/elasticsearch/lib/api/types'; import { QueryClientProvider } from '@tanstack/react-query'; import { useSearchAlertsQuery } from '@kbn/alerts-ui-shared/src/common/hooks/use_search_alerts_query'; import { DEFAULT_ALERTS_PAGE_SIZE } from '@kbn/alerts-ui-shared/src/common/constants'; diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/configuration.tsx b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/configuration.tsx index 59e160cb77289..ba6b1d9cf62e5 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/configuration.tsx +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/configuration.tsx @@ -19,7 +19,7 @@ import { ALERT_STATUS, TIMESTAMP, } from '@kbn/rule-data-utils'; -import { SortCombinations } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { SortCombinations } from '@elastic/elasticsearch/lib/api/types'; import { FieldFormatsRegistry } from '@kbn/field-formats-plugin/common'; import { i18n } from '@kbn/i18n'; import { FEATURE_LABEL } from '../translations'; diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/hooks/constants.ts b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/hooks/constants.ts index aee55831e833a..9075475768ef1 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/hooks/constants.ts +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/hooks/constants.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { SortCombinations } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { SortCombinations } from '@elastic/elasticsearch/lib/api/types'; export const DefaultSort: SortCombinations[] = [ { diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.ts b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.ts index 1f35d02f8d72f..e3e1666b74164 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.ts +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.ts @@ -5,7 +5,7 @@ * 2.0. */ import { useCallback, useContext, useEffect, useMemo } from 'react'; -import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { ALERT_CASE_IDS, isSiemRuleType } from '@kbn/rule-data-utils'; import { AlertsTableContext } from '../contexts/alerts_table_context'; diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_untrack_alerts_by_query.tsx b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_untrack_alerts_by_query.tsx index 88c878aa47a66..558d4d5a4a8e2 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_untrack_alerts_by_query.tsx +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_untrack_alerts_by_query.tsx @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { useMutation } from '@tanstack/react-query'; -import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; import { INTERNAL_BASE_ALERTING_API_PATH } from '@kbn/alerting-plugin/common'; import { AlertsQueryContext } from '@kbn/alerts-ui-shared/src/common/contexts/alerts_query_context'; import { useKibana } from '../../../../common'; diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_sorting.ts b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_sorting.ts index 78eee5cf9657c..328c1078c8bab 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_sorting.ts +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_sorting.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { SortCombinations } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { SortCombinations } from '@elastic/elasticsearch/lib/api/types'; import type { EuiDataGridSorting } from '@elastic/eui'; import { useCallback, useMemo, useState } from 'react'; diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/field_browser/mock.ts b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/field_browser/mock.ts index 59d9c33838250..321b0848cf9f8 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/field_browser/mock.ts +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/field_browser/mock.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/types'; import { BrowserFields } from '@kbn/rule-registry-plugin/common'; const DEFAULT_INDEX_PATTERN = [ diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/types.ts b/x-pack/platform/plugins/shared/triggers_actions_ui/public/types.ts index 0d7f3fea23477..b854e5beaa939 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/types.ts +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/types.ts @@ -5,10 +5,7 @@ * 2.0. */ -import { - QueryDslQueryContainer, - SortCombinations, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { QueryDslQueryContainer, SortCombinations } from '@elastic/elasticsearch/lib/api/types'; import type { EuiDataGridCellPopoverElementProps, EuiDataGridCellProps, diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/server/data/lib/time_series_query.test.ts b/x-pack/platform/plugins/shared/triggers_actions_ui/server/data/lib/time_series_query.test.ts index efc802dc73d3c..63902ff9bd295 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/server/data/lib/time_series_query.test.ts +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/server/data/lib/time_series_query.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import * as estypes from '@elastic/elasticsearch/lib/api/types'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { Logger } from '@kbn/core/server'; import { TimeSeriesQuery, timeSeriesQuery, getResultFromEs } from './time_series_query'; diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/server/data/lib/time_series_query.ts b/x-pack/platform/plugins/shared/triggers_actions_ui/server/data/lib/time_series_query.ts index a07c15f11ad0a..85e54cd061926 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/server/data/lib/time_series_query.ts +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/server/data/lib/time_series_query.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { Logger } from '@kbn/core/server'; import type { ElasticsearchClient } from '@kbn/core/server'; import { getEsErrorMessage } from '@kbn/alerting-plugin/server'; diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/find_related_entities/analyze_fetched_related_entities.ts b/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/find_related_entities/analyze_fetched_related_entities.ts index 893533629ff06..708ae462260f5 100644 --- a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/find_related_entities/analyze_fetched_related_entities.ts +++ b/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/find_related_entities/analyze_fetched_related_entities.ts @@ -40,7 +40,7 @@ export interface RelatedEntityFromSearchResults { function getPromptForFoundEntity({ entity, analysis, highlight }: RelatedEntityFromSearchResults) { return `## Entity: ${formatEntity(entity)} - + ${toBlockquote(`### Search highlights for ${formatEntity(entity)} ${JSON.stringify(highlight)}`)} `; @@ -88,7 +88,7 @@ function getInputPromptBase({ ## Data analysis ${JSON.stringify(analysis)} - + ## Log patterns for ${formatEntity(entity)} ${logPatternsPrompt} @@ -102,7 +102,7 @@ function getInputPromptBase({ ${searches .map(({ fragments, appearsAs }) => { return `## Appears as: ${appearsAs} - + ### Fragments: ${fragments.map((fragment) => `- \`${fragment}\``).join('\n')}`; }) @@ -243,9 +243,9 @@ export async function analyzeFetchedRelatedEntities({ logger.debug(() => `Found ${foundEntities.length} entities via keyword searches`); const system = `${RCA_SYSTEM_PROMPT_BASE} - + ${RCA_PROMPT_ENTITIES} - + ${RCA_PROMPT_DEPENDENCIES}`; const inputPromptBase = getInputPromptBase({ @@ -285,7 +285,7 @@ export async function analyzeFetchedRelatedEntities({ connectorId, system: request.system, input: `${inputPromptBase} - + # Found entities ${request.texts.map((text) => text.text).join('\n\n')} @@ -377,7 +377,7 @@ export async function analyzeFetchedRelatedEntities({ const groupingFieldAnalysis = await Promise.all( keywordSearchResults.hits.hits.map(async (hit) => { return limiter(async () => { - const groupValue = hit.fields![groupingField][0] as string; + const groupValue = hit.fields![groupingField]?.[0] as string; const analysisForGroupingField = await analyzeDocuments({ esClient, diff --git a/x-pack/solutions/observability/packages/utils_browser/hooks/use_abortable_async.ts b/x-pack/solutions/observability/packages/utils_browser/hooks/use_abortable_async.ts index f0d2bf4a05872..17dfde0736477 100644 --- a/x-pack/solutions/observability/packages/utils_browser/hooks/use_abortable_async.ts +++ b/x-pack/solutions/observability/packages/utils_browser/hooks/use_abortable_async.ts @@ -58,12 +58,17 @@ export function useAbortableAsync( const controller = new AbortController(); controllerRef.current = controller; + function isRequestStale() { + return controllerRef.current !== controller; + } + if (clearValueOnNext) { setValue(undefined); setError(undefined); } function handleError(err: Error) { + if (isRequestStale()) return; setError(err); if (unsetValueOnError) { setValue(undefined); @@ -78,11 +83,15 @@ export function useAbortableAsync( setLoading(true); response .then((nextValue) => { + if (isRequestStale()) return; setError(undefined); setValue(nextValue); }) .catch(handleError) - .finally(() => setLoading(false)); + .finally(() => { + if (isRequestStale()) return; + setLoading(false); + }); } else { setError(undefined); setValue(response); diff --git a/x-pack/solutions/observability/packages/utils_server/entities/get_data_streams_for_entity.ts b/x-pack/solutions/observability/packages/utils_server/entities/get_data_streams_for_entity.ts index 43d9134c7aaf3..9265a461db22e 100644 --- a/x-pack/solutions/observability/packages/utils_server/entities/get_data_streams_for_entity.ts +++ b/x-pack/solutions/observability/packages/utils_server/entities/get_data_streams_for_entity.ts @@ -54,7 +54,20 @@ export async function getDataStreamsForEntity({ }); const dataStreams = uniq( - compact(await resolveIndexResponse.indices.flatMap((idx) => idx.data_stream)) + compact([ + /* Check both data streams and indices. + * The response body shape differs depending on the request. Example: + * GET _resolve/index/logs-*-default* will return data in the `data_streams` key. + * GET _resolve/index/.ds-logs-*-default* will return data in the `indices` key */ + ...resolveIndexResponse.indices.flatMap((idx) => { + const remoteCluster = idx.name.includes(':') ? idx.name.split(':')[0] : null; + if (remoteCluster) { + return `${remoteCluster}:${idx.data_stream}`; + } + return idx.data_stream; + }), + ...resolveIndexResponse.data_streams.map((ds) => ds.name), + ]) ); return { diff --git a/x-pack/solutions/observability/plugins/apm/common/service_health_status.ts b/x-pack/solutions/observability/plugins/apm/common/service_health_status.ts index 65427caba7473..f9b960693e391 100644 --- a/x-pack/solutions/observability/plugins/apm/common/service_health_status.ts +++ b/x-pack/solutions/observability/plugins/apm/common/service_health_status.ts @@ -38,13 +38,19 @@ export function getServiceHealthStatusColor( euiTheme: EuiThemeComputed, status: ServiceHealthStatus ) { + const isAmsterdam = euiTheme.themeName === 'EUI_THEME_AMSTERDAM'; + switch (status) { case ServiceHealthStatus.healthy: - return euiTheme.colors.success; + return isAmsterdam + ? euiTheme.colors.vis.euiColorVis0 + : euiTheme.colors.vis.euiColorVisSuccess0; case ServiceHealthStatus.warning: - return euiTheme.colors.warning; + return isAmsterdam ? euiTheme.colors.vis.euiColorVis5 : euiTheme.colors.vis.euiColorVis9; case ServiceHealthStatus.critical: - return euiTheme.colors.danger; + return isAmsterdam + ? euiTheme.colors.vis.euiColorVis9 + : euiTheme.colors.vis.euiColorSeverity14; case ServiceHealthStatus.unknown: return euiTheme.colors.mediumShade; } @@ -54,13 +60,21 @@ export function getServiceHealthStatusBadgeColor( euiTheme: EuiThemeComputed, status: ServiceHealthStatus ) { + const isAmsterdam = euiTheme.themeName === 'EUI_THEME_AMSTERDAM'; + switch (status) { case ServiceHealthStatus.healthy: - return euiTheme.colors.success; + return isAmsterdam + ? euiTheme.colors.vis.euiColorVisBehindText0 + : euiTheme.colors.vis.euiColorVisSuccess0; case ServiceHealthStatus.warning: - return euiTheme.colors.warning; + return isAmsterdam + ? euiTheme.colors.vis.euiColorVisBehindText5 + : euiTheme.colors.vis.euiColorVis9; case ServiceHealthStatus.critical: - return euiTheme.colors.danger; + return isAmsterdam + ? euiTheme.colors.vis.euiColorVisBehindText9 + : euiTheme.colors.vis.euiColorSeverity12; case ServiceHealthStatus.unknown: return euiTheme.colors.mediumShade; } diff --git a/x-pack/solutions/observability/plugins/apm/common/viz_colors.ts b/x-pack/solutions/observability/plugins/apm/common/viz_colors.ts index 20d525c914549..f2346fbad22f8 100644 --- a/x-pack/solutions/observability/plugins/apm/common/viz_colors.ts +++ b/x-pack/solutions/observability/plugins/apm/common/viz_colors.ts @@ -5,24 +5,24 @@ * 2.0. */ -import { euiLightVars as lightTheme } from '@kbn/ui-theme'; +import type { EuiThemeComputed } from '@elastic/eui'; -function getVizColorsForTheme(theme = lightTheme) { +function getVizColorsForTheme(euiTheme: EuiThemeComputed) { return [ - theme.euiColorVis0, - theme.euiColorVis1, - theme.euiColorVis2, - theme.euiColorVis3, - theme.euiColorVis4, - theme.euiColorVis5, - theme.euiColorVis6, - theme.euiColorVis7, - theme.euiColorVis8, - theme.euiColorVis9, + euiTheme.colors.vis.euiColorVis0, + euiTheme.colors.vis.euiColorVis1, + euiTheme.colors.vis.euiColorVis2, + euiTheme.colors.vis.euiColorVis3, + euiTheme.colors.vis.euiColorVis4, + euiTheme.colors.vis.euiColorVis5, + euiTheme.colors.vis.euiColorVis6, + euiTheme.colors.vis.euiColorVis7, + euiTheme.colors.vis.euiColorVis8, + euiTheme.colors.vis.euiColorVis9, ]; } -export function getVizColorForIndex(index = 0, theme = lightTheme) { - const colors = getVizColorsForTheme(theme); +export function getVizColorForIndex(index = 0, euiTheme: EuiThemeComputed) { + const colors = getVizColorsForTheme(euiTheme); return colors[index % colors.length]; } diff --git a/x-pack/solutions/observability/plugins/apm/dev_docs/testing.md b/x-pack/solutions/observability/plugins/apm/dev_docs/testing.md index c1c83768fd745..ce252f0926be2 100644 --- a/x-pack/solutions/observability/plugins/apm/dev_docs/testing.md +++ b/x-pack/solutions/observability/plugins/apm/dev_docs/testing.md @@ -141,7 +141,7 @@ Tests run on buildkite PR pipeline are parallelized (8 parallel jobs) and are or ```yml ... depends_on: build - parallelism: 8 + parallelism: 3 ... ``` @@ -150,7 +150,7 @@ Tests run on buildkite PR pipeline are parallelized (8 parallel jobs) and are or #### Start Cypress dashboard ``` -node x-pack/solutions/observability/plugins/apm/scripts/test/e2e --headed +node x-pack/solutions/observability/plugins/apm/scripts/test/e2e --open ``` #### Run tests @@ -159,6 +159,12 @@ node x-pack/solutions/observability/plugins/apm/scripts/test/e2e --headed node x-pack/solutions/observability/plugins/apm/scripts/test/e2e ``` +#### Run tests in headed mode + +``` +node x-pack/solutions/observability/plugins/apm/scripts/test/e2e --headed +``` + ### A11y checks Accessibility tests are added on the e2e with `checkA11y()`, they will run together with cypress. diff --git a/x-pack/solutions/observability/plugins/apm/ftr_e2e/cypress/e2e/service_overview/otel_service_overview_and_transactions.cy.ts b/x-pack/solutions/observability/plugins/apm/ftr_e2e/cypress/e2e/service_overview/otel_service_overview_and_transactions.cy.ts index 8554a3302f9b7..04edc6f42d6c4 100644 --- a/x-pack/solutions/observability/plugins/apm/ftr_e2e/cypress/e2e/service_overview/otel_service_overview_and_transactions.cy.ts +++ b/x-pack/solutions/observability/plugins/apm/ftr_e2e/cypress/e2e/service_overview/otel_service_overview_and_transactions.cy.ts @@ -20,6 +20,12 @@ const baseUrl = url.format({ query: { rangeFrom: start, rangeTo: end }, }); +const transactionTabPath = '/app/apm/services/sendotlp-synth/transactions/view'; +const transactionUrl = url.format({ + pathname: transactionTabPath, + query: { rangeFrom: start, rangeTo: end, transactionName: 'parent-synth' }, +}); + describe('Service Overview', () => { before(() => { synthtraceOtel.index( @@ -117,6 +123,13 @@ describe('Service Overview', () => { cy.contains('a', 'parent-synth').click(); cy.contains('h5', 'parent-synth'); }); + it('shows transaction summary', () => { + cy.visitKibana(transactionUrl); + + cy.getByTestSubj('apmHttpInfoRequestMethod').should('exist'); + cy.getByTestSubj('apmHttpInfoUrl').should('exist'); + cy.getByTestSubj('apmHttpStatusBadge').should('exist'); + }); }); describe('errors', () => { diff --git a/x-pack/solutions/observability/plugins/apm/ftr_e2e/cypress/e2e/transaction_details/transaction_details.cy.ts b/x-pack/solutions/observability/plugins/apm/ftr_e2e/cypress/e2e/transaction_details/transaction_details.cy.ts index 0ef8fb40ceb38..b6ebd1813fdaf 100644 --- a/x-pack/solutions/observability/plugins/apm/ftr_e2e/cypress/e2e/transaction_details/transaction_details.cy.ts +++ b/x-pack/solutions/observability/plugins/apm/ftr_e2e/cypress/e2e/transaction_details/transaction_details.cy.ts @@ -123,6 +123,21 @@ describe('Transaction details', () => { cy.url().should('include', 'opbeans-java/errors'); }); + describe('Trace sample summary', () => { + it('shows transaction summary', () => { + cy.visitKibana( + `/app/apm/services/opbeans-node/transactions/view?${new URLSearchParams({ + ...timeRange, + transactionName: 'GET /api/product/:id', + })}` + ); + + cy.getByTestSubj('apmHttpInfoRequestMethod').should('exist'); + cy.getByTestSubj('apmHttpInfoUrl').should('exist'); + cy.getByTestSubj('apmHttpStatusBadge').should('exist'); + }); + }); + describe('when navigating to a trace sample', () => { it('keeps the same trace sample after reloading the page', () => { cy.visitKibana( diff --git a/x-pack/solutions/observability/plugins/apm/ftr_e2e/package.json b/x-pack/solutions/observability/plugins/apm/ftr_e2e/package.json index 1bad8ad8eeb82..6b8749fc1e5be 100644 --- a/x-pack/solutions/observability/plugins/apm/ftr_e2e/package.json +++ b/x-pack/solutions/observability/plugins/apm/ftr_e2e/package.json @@ -8,6 +8,7 @@ "cypress": "NODE_OPTIONS=--openssl-legacy-provider node ../../../../security/plugins/security_solution/scripts/start_cypress_parallel --config-file ../observability/plugins/apm/ftr_e2e/cypress.config.ts --ftr-config-file ../../../../../test/apm_cypress/cli_config", "cypress:open": "yarn cypress open", "cypress:run": "yarn cypress run", + "cypress:run:headed": "yarn cypress run --headed", "junit:merge": "../../../../../../node_modules/.bin/mochawesome-merge ../../../../../../target/kibana-apm/cypress/results/mochawesome*.json > ../../../../../../target/kibana-apm/cypress/results/output.json && ../../../../../../node_modules/.bin/marge ../../../../../../target/kibana-apm/cypress/results/output.json --reportDir ../../../../../../target/kibana-apm/cypress/results && yarn junit:transform && mkdir -p ../../../../../../target/junit && cp ../../../../../../target/kibana-apm/cypress/results/*.xml ../../../../../../target/junit/", "junit:transform": "node ../../../../security/plugins/security_solution/scripts/junit_transformer --pathPattern '../../../../../../target/kibana-apm/cypress/results/*.xml' --rootDirectory ../../../../../../ --reportName 'APM Cypress' --writeInPlace" } diff --git a/x-pack/solutions/observability/plugins/apm/public/components/app/service_dependencies/service_dependencies_breakdown_chart.tsx b/x-pack/solutions/observability/plugins/apm/public/components/app/service_dependencies/service_dependencies_breakdown_chart.tsx index b380765d2451d..dba272c260072 100644 --- a/x-pack/solutions/observability/plugins/apm/public/components/app/service_dependencies/service_dependencies_breakdown_chart.tsx +++ b/x-pack/solutions/observability/plugins/apm/public/components/app/service_dependencies/service_dependencies_breakdown_chart.tsx @@ -5,6 +5,7 @@ * 2.0. */ import React from 'react'; +import { useEuiTheme } from '@elastic/eui'; import { getVizColorForIndex } from '../../../../common/viz_colors'; import type { Coordinate, TimeSeries } from '../../../../typings/timeseries'; import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context'; @@ -15,6 +16,7 @@ import { BreakdownChart } from '../../shared/charts/breakdown_chart'; export function ServiceDependenciesBreakdownChart({ height }: { height: number }) { const { serviceName } = useApmServiceContext(); + const { euiTheme } = useEuiTheme(); const { query: { kuery, environment, rangeFrom, rangeTo }, @@ -50,7 +52,7 @@ export function ServiceDependenciesBreakdownChart({ height }: { height: number } title: item.title, data: item.data, type: 'area', - color: getVizColorForIndex(index), + color: getVizColorForIndex(index, euiTheme), }; }) ?? []; diff --git a/x-pack/solutions/observability/plugins/apm/public/components/app/service_map/cytoscape_options.ts b/x-pack/solutions/observability/plugins/apm/public/components/app/service_map/cytoscape_options.ts index 9cf1acccd7b79..f54cf04d460ac 100644 --- a/x-pack/solutions/observability/plugins/apm/public/components/app/service_map/cytoscape_options.ts +++ b/x-pack/solutions/observability/plugins/apm/public/components/app/service_map/cytoscape_options.ts @@ -100,7 +100,7 @@ function isService(el: cytoscape.NodeSingular) { const getStyle = ( euiTheme: EuiThemeComputed, isTraceExplorerEnabled: boolean -): cytoscape.Stylesheet[] => { +): cytoscape.StylesheetJson => { const lineColor = euiTheme.colors.mediumShade; return [ { diff --git a/x-pack/solutions/observability/plugins/apm/public/components/app/storage_explorer/storage_chart.tsx b/x-pack/solutions/observability/plugins/apm/public/components/app/storage_explorer/storage_chart.tsx index 0531c176c2201..77bfa69a3706d 100644 --- a/x-pack/solutions/observability/plugins/apm/public/components/app/storage_explorer/storage_chart.tsx +++ b/x-pack/solutions/observability/plugins/apm/public/components/app/storage_explorer/storage_chart.tsx @@ -5,7 +5,7 @@ * 2.0. */ import React from 'react'; -import { euiPaletteColorBlind } from '@elastic/eui'; +import { euiPaletteColorBlind, useEuiTheme } from '@elastic/eui'; import { AreaSeries, Axis, @@ -17,6 +17,7 @@ import { } from '@elastic/charts'; import { useChartThemes } from '@kbn/observability-shared-plugin/public'; import { i18n } from '@kbn/i18n'; +import { getVizColorForIndex } from '../../../../common/viz_colors'; import { useProgressiveFetcher } from '../../../hooks/use_progressive_fetcher'; import { useTimeRange } from '../../../hooks/use_time_range'; import { useApmParams } from '../../../hooks/use_apm_params'; @@ -30,6 +31,7 @@ import { asDynamicBytes } from '../../../../common/utils/formatters'; export function StorageChart() { const { core } = useApmPluginContext(); const chartThemes = useChartThemes(); + const { euiTheme } = useEuiTheme(); const euiPaletteColorBlindRotations = 3; const groupedPalette = euiPaletteColorBlind({ @@ -116,7 +118,7 @@ export function StorageChart() { gridLine={{ visible: true }} tickFormat={asDynamicBytes} /> - {storageTimeSeries.map((serie) => ( + {storageTimeSeries.map((serie, index) => ( ))} diff --git a/x-pack/solutions/observability/plugins/apm/public/components/shared/charts/breakdown_chart/index.tsx b/x-pack/solutions/observability/plugins/apm/public/components/shared/charts/breakdown_chart/index.tsx index d9cbec2c86bc6..a4893d4f3dbdb 100644 --- a/x-pack/solutions/observability/plugins/apm/public/components/shared/charts/breakdown_chart/index.tsx +++ b/x-pack/solutions/observability/plugins/apm/public/components/shared/charts/breakdown_chart/index.tsx @@ -26,6 +26,7 @@ import moment from 'moment'; import React from 'react'; import { useHistory } from 'react-router-dom'; import { useChartThemes } from '@kbn/observability-shared-plugin/public'; +import { getVizColorForIndex } from '../../../../../common/viz_colors'; import type { Annotation } from '../../../../../common/annotations'; import { asAbsoluteDateTime, @@ -142,7 +143,7 @@ export function BreakdownChart({ )} {timeseries?.length ? ( - timeseries.map((serie) => { + timeseries.map((serie, index) => { return ( ); diff --git a/x-pack/solutions/observability/plugins/apm/public/components/shared/charts/timeseries_chart.tsx b/x-pack/solutions/observability/plugins/apm/public/components/shared/charts/timeseries_chart.tsx index 75be9419fa111..6598a5ed53a55 100644 --- a/x-pack/solutions/observability/plugins/apm/public/components/shared/charts/timeseries_chart.tsx +++ b/x-pack/solutions/observability/plugins/apm/public/components/shared/charts/timeseries_chart.tsx @@ -33,6 +33,7 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useHistory } from 'react-router-dom'; import { useChartThemes } from '@kbn/observability-shared-plugin/public'; +import { getVizColorForIndex } from '../../../../common/viz_colors'; import { isExpectedBoundsComparison } from '../time_comparison/get_comparison_options'; import { useChartPointerEventContext } from '../../../context/chart_pointer_event/use_chart_pointer_event_context'; @@ -222,7 +223,7 @@ export function TimeseriesChart({ ]} style={endZoneRectAnnotationStyle} /> - {allSeries.map((serie) => { + {allSeries.map((serie, index) => { const Series = getChartType(serie.type); return ( @@ -239,7 +240,7 @@ export function TimeseriesChart({ stackAccessors={serie.stackAccessors ?? undefined} markSizeAccessor={serie.markSizeAccessor} data={isEmpty ? [] : serie.data} - color={serie.color} + color={getVizColorForIndex(index, euiTheme)} curve={CurveType.CURVE_MONOTONE_X} hideInLegend={serie.hideLegend} fit={serie.fit ?? undefined} diff --git a/x-pack/solutions/observability/plugins/apm/public/components/shared/summary/http_info_summary_item/index.tsx b/x-pack/solutions/observability/plugins/apm/public/components/shared/summary/http_info_summary_item/index.tsx index 5732c426e2610..320c59a2b8233 100644 --- a/x-pack/solutions/observability/plugins/apm/public/components/shared/summary/http_info_summary_item/index.tsx +++ b/x-pack/solutions/observability/plugins/apm/public/components/shared/summary/http_info_summary_item/index.tsx @@ -5,21 +5,20 @@ * 2.0. */ -import { EuiBadge, EuiToolTip } from '@elastic/eui'; +import { EuiBadge, EuiToolTip, useEuiTheme } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import styled from '@emotion/styled'; -import { truncate, unit } from '../../../../utils/style'; +import { css } from '@emotion/react'; +import { unit } from '../../../../utils/style'; import { HttpStatusBadge } from '../http_status_badge'; -const HttpInfoBadge = styled(EuiBadge)` - margin-right: ${({ theme }) => theme.euiTheme.size.xs}; -`; - -const Url = styled('span')` +const urlStyles = css` display: inline-block; vertical-align: bottom; - ${truncate(unit * 24)}; + max-width: ${unit * 24}px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; `; interface HttpInfoProps { method?: string; @@ -27,11 +26,9 @@ interface HttpInfoProps { url: string; } -const Span = styled('span')` - white-space: nowrap; -`; - export function HttpInfoSummaryItem({ status, method, url }: HttpInfoProps) { + const { euiTheme } = useEuiTheme(); + if (!url) { return null; } @@ -41,18 +38,29 @@ export function HttpInfoSummaryItem({ status, method, url }: HttpInfoProps) { }); return ( - - + + {method && ( - <>{method.toUpperCase()} + {method.toUpperCase()} )}{' '} - {url} + + {url} + - + {status && } - + ); } diff --git a/x-pack/solutions/observability/plugins/apm/public/components/shared/summary/http_status_badge/index.tsx b/x-pack/solutions/observability/plugins/apm/public/components/shared/summary/http_status_badge/index.tsx index e3f7f623642db..6ed20b0010e24 100644 --- a/x-pack/solutions/observability/plugins/apm/public/components/shared/summary/http_status_badge/index.tsx +++ b/x-pack/solutions/observability/plugins/apm/public/components/shared/summary/http_status_badge/index.tsx @@ -21,7 +21,9 @@ export function HttpStatusBadge({ status }: HttpStatusBadgeProps) { return ( - {status} {statusCodes[status.toString()]} + + {status} {statusCodes[status.toString()]} + ); diff --git a/x-pack/solutions/observability/plugins/apm/scripts/test/e2e.js b/x-pack/solutions/observability/plugins/apm/scripts/test/e2e.js index 12708ea449218..cc951f694d3b7 100644 --- a/x-pack/solutions/observability/plugins/apm/scripts/test/e2e.js +++ b/x-pack/solutions/observability/plugins/apm/scripts/test/e2e.js @@ -17,15 +17,22 @@ const { argv } = yargs(process.argv.slice(2)) type: 'boolean', description: 'Runs Cypress in headed mode', }) + .option('open', { + default: false, + type: 'boolean', + description: 'Opens Cypress dashboard', + }) .help(); const e2eDir = path.join(__dirname, '../../ftr_e2e'); function runTests() { - const mode = argv.headed ? 'open' : 'run'; - console.log(`Running e2e tests: "yarn cypress:${mode}"`); + const mode = argv.open ? 'open' : 'run'; + const isHeaded = mode === 'run' && argv.headed ? ':headed' : ''; + + console.log(`Running e2e tests: "yarn cypress:${mode}${isHeaded}"`); - return childProcess.spawnSync('yarn', [`cypress:${mode}`], { + return childProcess.spawnSync('yarn', [`cypress:${mode}${isHeaded}`], { cwd: e2eDir, encoding: 'utf8', stdio: 'inherit', diff --git a/x-pack/solutions/observability/plugins/apm/server/lib/helpers/get_internal_saved_objects_client.ts b/x-pack/solutions/observability/plugins/apm/server/lib/helpers/get_internal_saved_objects_client.ts index 9566fb9895928..714ecd310ecd3 100644 --- a/x-pack/solutions/observability/plugins/apm/server/lib/helpers/get_internal_saved_objects_client.ts +++ b/x-pack/solutions/observability/plugins/apm/server/lib/helpers/get_internal_saved_objects_client.ts @@ -5,8 +5,29 @@ * 2.0. */ -import type { CoreStart } from '@kbn/core/server'; +import { kibanaRequestFactory } from '@kbn/core-http-server-utils'; +import { SECURITY_EXTENSION_ID, type CoreStart, SavedObjectsClient } from '@kbn/core/server'; +import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; export async function getInternalSavedObjectsClient(coreStart: CoreStart) { - return coreStart.savedObjects.createInternalRepository(); + return new SavedObjectsClient(coreStart.savedObjects.createInternalRepository()); +} + +export function getInternalSavedObjectsClientForSpaceId(coreStart: CoreStart, spaceId?: string) { + const request = kibanaRequestFactory({ + headers: {}, + path: '/', + route: { settings: {} }, + url: { href: '', hash: '' } as URL, + raw: { req: { url: '/' } } as any, + }); + + if (spaceId && spaceId !== DEFAULT_SPACE_ID) { + coreStart.http.basePath.set(request, `/s/${spaceId}`); + } + + // soClient as kibana internal users, be careful on how you use it, security is not enabled + return coreStart.savedObjects.getScopedClient(request, { + excludedExtensions: [SECURITY_EXTENSION_ID], + }); } diff --git a/x-pack/solutions/observability/plugins/apm/server/plugin.ts b/x-pack/solutions/observability/plugins/apm/server/plugin.ts index e8e844b799849..e06a8afc8510c 100644 --- a/x-pack/solutions/observability/plugins/apm/server/plugin.ts +++ b/x-pack/solutions/observability/plugins/apm/server/plugin.ts @@ -200,6 +200,7 @@ export class APMPlugin // This will add an API key to all existing APM package policies addApiKeysToEveryPackagePolicyIfMissing({ coreStartPromise: getCoreStart(), + licensing: plugins.licensing, pluginStartPromise: getPluginStart(), logger: this.logger, }).catch((e) => { diff --git a/x-pack/solutions/observability/plugins/apm/server/routes/entities/utils/merge_entities.test.ts b/x-pack/solutions/observability/plugins/apm/server/routes/entities/utils/merge_entities.test.ts index 867c8b10a8739..84fa43911f496 100644 --- a/x-pack/solutions/observability/plugins/apm/server/routes/entities/utils/merge_entities.test.ts +++ b/x-pack/solutions/observability/plugins/apm/server/routes/entities/utils/merge_entities.test.ts @@ -302,4 +302,27 @@ describe('mergeEntities', () => { }, ]); }); + it('has a single data stream type and no environment', () => { + const entities: EntityLatestServiceRaw[] = [ + { + 'data_stream.type': 'logs', + 'agent.name': ['nodejs', 'nodejs'], + 'entity.last_seen_timestamp': '2024-12-13T14:52:35.461Z', + 'service.name': 'service-1', + 'entity.type': 'built_in_services_from_ecs_data', + 'entity.id': 'service-1:test', + 'entity.display_name': 'service-1', + }, + ]; + const result = mergeEntities({ entities }); + expect(result).toEqual([ + { + agentName: 'nodejs' as AgentName, + dataStreamTypes: ['logs'], + environments: [], + lastSeenTimestamp: '2024-12-13T14:52:35.461Z', + serviceName: 'service-1', + }, + ]); + }); }); diff --git a/x-pack/solutions/observability/plugins/apm/server/routes/entities/utils/merge_entities.ts b/x-pack/solutions/observability/plugins/apm/server/routes/entities/utils/merge_entities.ts index 383b07606de0a..bb1741116f173 100644 --- a/x-pack/solutions/observability/plugins/apm/server/routes/entities/utils/merge_entities.ts +++ b/x-pack/solutions/observability/plugins/apm/server/routes/entities/utils/merge_entities.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { compact, uniq } from 'lodash'; +import { castArray, compact, uniq } from 'lodash'; import type { EntityDataStreamType } from '@kbn/observability-shared-plugin/common'; import type { EntityLatestServiceRaw } from '../types'; import type { AgentName } from '../../../../typings/es_schemas/ui/fields/agent'; @@ -49,7 +49,7 @@ function mergeFunc(entity: EntityLatestServiceRaw, existingEntity?: MergedServic if (!existingEntity) { return { ...commonEntityFields, - dataStreamTypes: uniq(entity['data_stream.type']), + dataStreamTypes: uniq(castArray(entity['data_stream.type'])), environments: uniq( compact( Array.isArray(entity['service.environment']) @@ -62,7 +62,10 @@ function mergeFunc(entity: EntityLatestServiceRaw, existingEntity?: MergedServic return { ...commonEntityFields, dataStreamTypes: uniq( - compact([...(existingEntity?.dataStreamTypes ?? []), ...entity['data_stream.type']]) + compact([ + ...(existingEntity?.dataStreamTypes ?? []), + ...castArray(entity['data_stream.type']), + ]) ), environments: uniq(compact([...existingEntity?.environments, entity['service.environment']])), }; diff --git a/x-pack/solutions/observability/plugins/apm/server/routes/fleet/api_keys/add_api_keys_to_policies_if_missing.ts b/x-pack/solutions/observability/plugins/apm/server/routes/fleet/api_keys/add_api_keys_to_policies_if_missing.ts index a5b16d6d44da6..f556ebe04ccd5 100644 --- a/x-pack/solutions/observability/plugins/apm/server/routes/fleet/api_keys/add_api_keys_to_policies_if_missing.ts +++ b/x-pack/solutions/observability/plugins/apm/server/routes/fleet/api_keys/add_api_keys_to_policies_if_missing.ts @@ -7,9 +7,12 @@ import { omit } from 'lodash'; import type { PackagePolicy } from '@kbn/fleet-plugin/common'; -import type { CoreStart, Logger } from '@kbn/core/server'; +import type { CoreStart, Logger, SavedObjectsClientContract } from '@kbn/core/server'; import type { FleetStartContract } from '@kbn/fleet-plugin/server'; -import { getInternalSavedObjectsClient } from '../../../lib/helpers/get_internal_saved_objects_client'; +import type { LicensingPluginSetup } from '@kbn/licensing-plugin/server'; +import { filter, lastValueFrom, take } from 'rxjs'; + +import { getInternalSavedObjectsClientForSpaceId } from '../../../lib/helpers/get_internal_saved_objects_client'; import type { APMPluginStartDependencies } from '../../../types'; import { getApmPackagePolicies } from '../get_apm_package_policies'; import { createApmAgentConfigApiKey, createApmSourceMapApiKey } from './create_apm_api_keys'; @@ -19,10 +22,12 @@ export async function addApiKeysToEveryPackagePolicyIfMissing({ coreStartPromise, pluginStartPromise, logger, + licensing, }: { coreStartPromise: Promise; pluginStartPromise: Promise; logger: Logger; + licensing: LicensingPluginSetup; }) { const coreStart = await coreStartPromise; const { fleet } = await pluginStartPromise; @@ -30,6 +35,18 @@ export async function addApiKeysToEveryPackagePolicyIfMissing({ return; } + // We need to wait for the licence feature to be available, + // to have our internal saved object client with encrypted saved object working properly + await lastValueFrom( + licensing.license$.pipe( + filter( + (licence) => + licence.getFeature('security').isEnabled && licence.getFeature('security').isAvailable + ), + take(1) + ) + ); + const apmFleetPolicies = await getApmPackagePolicies({ coreStart, fleetPluginStart: fleet, @@ -37,8 +54,13 @@ export async function addApiKeysToEveryPackagePolicyIfMissing({ return Promise.all( apmFleetPolicies.items.map((policy) => { + const savedObjectsClient = getInternalSavedObjectsClientForSpaceId( + coreStart, + policy.spaceIds?.[0] + ); return addApiKeysToPackagePolicyIfMissing({ policy, + savedObjectsClient, coreStart, fleet, logger, @@ -50,10 +72,12 @@ export async function addApiKeysToEveryPackagePolicyIfMissing({ export async function addApiKeysToPackagePolicyIfMissing({ policy, coreStart, + savedObjectsClient, fleet, logger, }: { policy: PackagePolicy; + savedObjectsClient: SavedObjectsClientContract; coreStart: CoreStart; fleet: FleetStartContract; logger: Logger; @@ -85,7 +109,7 @@ export async function addApiKeysToPackagePolicyIfMissing({ }); const internalESClient = coreStart.elasticsearch.client.asInternalUser; - const savedObjectsClient = await getInternalSavedObjectsClient(coreStart); + const newPolicy = await fleet.packagePolicyService.update( savedObjectsClient, internalESClient, diff --git a/x-pack/solutions/observability/plugins/apm/server/routes/fleet/get_apm_package_policies.ts b/x-pack/solutions/observability/plugins/apm/server/routes/fleet/get_apm_package_policies.ts index 22422155903ec..43e251daf0548 100644 --- a/x-pack/solutions/observability/plugins/apm/server/routes/fleet/get_apm_package_policies.ts +++ b/x-pack/solutions/observability/plugins/apm/server/routes/fleet/get_apm_package_policies.ts @@ -16,11 +16,11 @@ export async function getApmPackagePolicies({ coreStart: CoreStart; fleetPluginStart: NonNullable; }) { - // @ts-ignore const savedObjectsClient: SavedObjectsClientContract = await getInternalSavedObjectsClient( coreStart ); return await fleetPluginStart.packagePolicyService.list(savedObjectsClient, { kuery: 'ingest-package-policies.package.name:apm', + spaceId: '*', }); } diff --git a/x-pack/solutions/observability/plugins/apm/server/routes/fleet/register_fleet_policy_callbacks.ts b/x-pack/solutions/observability/plugins/apm/server/routes/fleet/register_fleet_policy_callbacks.ts index 65d099e9aea3d..4a32ab0178e03 100644 --- a/x-pack/solutions/observability/plugins/apm/server/routes/fleet/register_fleet_policy_callbacks.ts +++ b/x-pack/solutions/observability/plugins/apm/server/routes/fleet/register_fleet_policy_callbacks.ts @@ -122,7 +122,7 @@ function onPackagePolicyPostCreate({ coreStart: CoreStart; logger: Logger; }): PostPackagePolicyPostCreateCallback { - return async (packagePolicy) => { + return async (packagePolicy, savedObjectsClient) => { if (packagePolicy.package?.name !== 'apm') { return packagePolicy; } @@ -130,6 +130,7 @@ function onPackagePolicyPostCreate({ // add api key to new package policy await addApiKeysToPackagePolicyIfMissing({ policy: packagePolicy, + savedObjectsClient, coreStart, fleet, logger, diff --git a/x-pack/solutions/observability/plugins/apm/server/routes/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts b/x-pack/solutions/observability/plugins/apm/server/routes/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts index 4e3e45e00722c..7c55aa5e29724 100644 --- a/x-pack/solutions/observability/plugins/apm/server/routes/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts +++ b/x-pack/solutions/observability/plugins/apm/server/routes/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts @@ -6,7 +6,6 @@ */ import { sum, round } from 'lodash'; -import { euiLightVars as theme } from '@kbn/ui-theme'; import { kqlQuery, rangeQuery } from '@kbn/observability-plugin/server'; import { ProcessorEvent } from '@kbn/observability-plugin/common'; import { isFiniteNumber } from '../../../../../../common/utils/is_finite_number'; @@ -23,7 +22,6 @@ import { SERVICE_NAME, } from '../../../../../../common/es_fields/apm'; import { getBucketSize } from '../../../../../../common/utils/get_bucket_size'; -import { getVizColorForIndex } from '../../../../../../common/viz_colors'; import { JAVA_AGENT_NAMES } from '../../../../../../common/agent_name'; import { environmentQuery, @@ -179,7 +177,6 @@ export async function fetchAndTransformGcMetrics({ title: label, key: label, type: chartBase.type, - color: getVizColorForIndex(i, theme), overallValue, data, }; diff --git a/x-pack/solutions/observability/plugins/apm/server/routes/metrics/fetch_and_transform_metrics.ts b/x-pack/solutions/observability/plugins/apm/server/routes/metrics/fetch_and_transform_metrics.ts index b177bb7cde384..adccc0af6faa8 100644 --- a/x-pack/solutions/observability/plugins/apm/server/routes/metrics/fetch_and_transform_metrics.ts +++ b/x-pack/solutions/observability/plugins/apm/server/routes/metrics/fetch_and_transform_metrics.ts @@ -6,12 +6,10 @@ */ import type { Unionize } from 'utility-types'; -import { euiLightVars as theme } from '@kbn/ui-theme'; import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; import type { AggregationOptionsByType } from '@kbn/es-types'; import { kqlQuery, rangeQuery } from '@kbn/observability-plugin/server'; import { ProcessorEvent } from '@kbn/observability-plugin/common'; -import { getVizColorForIndex } from '../../../common/viz_colors'; import type { APMEventClient, APMEventESSearchRequest, @@ -53,7 +51,6 @@ export interface FetchAndTransformMetrics { title: string; key: string; type: ChartType; - color: string; overallValue: number; data: Coordinate[]; }>; @@ -139,7 +136,6 @@ export async function fetchAndTransformMetrics({ title: chartBase.series[seriesKey].title, key: seriesKey, type: chartBase.type, - color: chartBase.series[seriesKey].color || getVizColorForIndex(i, theme), overallValue, data: timeseriesData?.buckets.map((bucket) => { diff --git a/x-pack/solutions/observability/plugins/apm/server/routes/metrics/serverless/get_compute_usage_chart.ts b/x-pack/solutions/observability/plugins/apm/server/routes/metrics/serverless/get_compute_usage_chart.ts index b8e92dc7ac2a5..dda2fbe1c5d56 100644 --- a/x-pack/solutions/observability/plugins/apm/server/routes/metrics/serverless/get_compute_usage_chart.ts +++ b/x-pack/solutions/observability/plugins/apm/server/routes/metrics/serverless/get_compute_usage_chart.ts @@ -8,7 +8,6 @@ import { i18n } from '@kbn/i18n'; import { ProcessorEvent } from '@kbn/observability-plugin/common'; import { kqlQuery, rangeQuery, termQuery } from '@kbn/observability-plugin/server'; -import { euiLightVars as theme } from '@kbn/ui-theme'; import type { APMConfig } from '../../..'; import { FAAS_BILLED_DURATION, @@ -115,7 +114,6 @@ export async function getComputeUsageChart({ computeUsageBytesMs: aggregations?.avgComputeUsageBytesMs.value, countInvocations: aggregations?.countInvocations.value, }) ?? 0, - color: theme.euiColorVis0, data: timeseriesData.buckets.map((bucket) => { const computeUsage = convertComputeUsageToGbSec({ diff --git a/x-pack/solutions/observability/plugins/apm/server/routes/metrics/serverless/get_serverless_function_latency_chart.ts b/x-pack/solutions/observability/plugins/apm/server/routes/metrics/serverless/get_serverless_function_latency_chart.ts index 4735855188e9d..c0d0c4b943745 100644 --- a/x-pack/solutions/observability/plugins/apm/server/routes/metrics/serverless/get_serverless_function_latency_chart.ts +++ b/x-pack/solutions/observability/plugins/apm/server/routes/metrics/serverless/get_serverless_function_latency_chart.ts @@ -7,7 +7,6 @@ import { i18n } from '@kbn/i18n'; import { termQuery } from '@kbn/observability-plugin/server'; -import { euiLightVars as theme } from '@kbn/ui-theme'; import { isEmpty } from 'lodash'; import type { APMConfig } from '../../..'; import type { ApmTransactionDocumentType } from '../../../../common/document_type'; @@ -15,7 +14,6 @@ import { FAAS_BILLED_DURATION, FAAS_ID, METRICSET_NAME } from '../../../../commo import { LatencyAggregationType } from '../../../../common/latency_aggregation_types'; import type { RollupInterval } from '../../../../common/rollup'; import { isFiniteNumber } from '../../../../common/utils/is_finite_number'; -import { getVizColorForIndex } from '../../../../common/viz_colors'; import type { APMEventClient } from '../../../lib/helpers/create_es_client/create_apm_event_client'; import { getLatencyTimeseries } from '../../transactions/get_latency_charts'; import type { GenericMetricsChart } from '../fetch_and_transform_metrics'; @@ -86,7 +84,6 @@ async function getServerlessLatencySeries({ }), key: 'transaction_duration', type: 'linemark', - color: getVizColorForIndex(1, theme), overallValue: transactionLatency.overallAvgDuration ?? 0, data: transactionLatency.latencyTimeseries, }, diff --git a/x-pack/solutions/observability/plugins/apm/server/routes/transactions/breakdown/index.ts b/x-pack/solutions/observability/plugins/apm/server/routes/transactions/breakdown/index.ts index 2c52566fd6ef8..9d139c90ade16 100644 --- a/x-pack/solutions/observability/plugins/apm/server/routes/transactions/breakdown/index.ts +++ b/x-pack/solutions/observability/plugins/apm/server/routes/transactions/breakdown/index.ts @@ -20,14 +20,12 @@ import { import { environmentQuery } from '../../../../common/utils/environment_query'; import { getMetricsDateHistogramParams } from '../../../lib/helpers/metrics'; import { MAX_KPIS } from './constants'; -import { getVizColorForIndex } from '../../../../common/viz_colors'; import type { APMConfig } from '../../..'; import type { APMEventClient } from '../../../lib/helpers/create_es_client/create_apm_event_client'; export interface TransactionBreakdownResponse { timeseries: Array<{ title: string; - color: string; type: string; data: Array<{ x: number; y: number | null }>; hideLegend: boolean; @@ -176,7 +174,6 @@ export async function getTransactionBreakdown({ const { lowerCaseName, ...rest } = kpi; return { ...rest, - color: getVizColorForIndex(index), }; }); @@ -232,7 +229,6 @@ export async function getTransactionBreakdown({ const timeseries = kpis.map((kpi) => ({ title: kpi.name, - color: kpi.color, type: 'areaStacked', data: timeseriesPerSubtype[kpi.name], hideLegend: false, diff --git a/x-pack/solutions/observability/plugins/apm/tsconfig.json b/x-pack/solutions/observability/plugins/apm/tsconfig.json index 6d3bdcb18df55..be688ddd1da27 100644 --- a/x-pack/solutions/observability/plugins/apm/tsconfig.json +++ b/x-pack/solutions/observability/plugins/apm/tsconfig.json @@ -131,7 +131,8 @@ "@kbn/saved-search-plugin", "@kbn/charts-theme", "@kbn/response-ops-rule-params", - "@kbn/entityManager-plugin" + "@kbn/entityManager-plugin", + "@kbn/core-http-server-utils" ], "exclude": ["target/**/*"] } diff --git a/x-pack/solutions/observability/plugins/apm/typings/timeseries.ts b/x-pack/solutions/observability/plugins/apm/typings/timeseries.ts index 64ce2b59fe604..f1344558fe051 100644 --- a/x-pack/solutions/observability/plugins/apm/typings/timeseries.ts +++ b/x-pack/solutions/observability/plugins/apm/typings/timeseries.ts @@ -50,7 +50,7 @@ export interface APMChartSpec< data: TCoordinate[]; legendValue?: string; type: string; - color: string | SeriesColorsArray | SeriesColorAccessorFn; + color?: string | SeriesColorsArray | SeriesColorAccessorFn; areaColor?: string; fit?: Exclude | FitConfig; stackAccessors?: Accessor; diff --git a/x-pack/solutions/observability/plugins/infra/public/components/asset_details/tabs/dashboards/actions/actions.test.tsx b/x-pack/solutions/observability/plugins/infra/public/components/asset_details/tabs/dashboards/actions/actions.test.tsx index 27ae309078cad..bc1c59b3b8835 100644 --- a/x-pack/solutions/observability/plugins/infra/public/components/asset_details/tabs/dashboards/actions/actions.test.tsx +++ b/x-pack/solutions/observability/plugins/infra/public/components/asset_details/tabs/dashboards/actions/actions.test.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import { EditDashboard, UnlinkDashboard, LinkDashboard } from '.'; import { useTabSwitcherContext } from '../../../hooks/use_tab_switcher'; +import * as fetchCustomDashboards from '../../../hooks/use_fetch_custom_dashboards'; import * as hooks from '../../../hooks/use_saved_objects_permissions'; const TEST_CURRENT_DASHBOARD = { @@ -114,34 +115,61 @@ describe('Custom Dashboards Actions', () => { expect(screen.getByTestId('infraLinkDashboardMenu')).toBeDisabled(); expect(screen.getByTestId('infraLinkDashboardMenu')).toHaveTextContent('Link new dashboard'); }); - it('should render the unlink dashboard action when the user can unlink a dashboard', () => { - jest.spyOn(hooks, 'useSavedObjectUserPermissions').mockImplementation(() => ({ - canSave: true, - canDelete: true, - })); - render( - {}} - assetType="host" - currentDashboard={TEST_CURRENT_DASHBOARD} - /> - ); - expect(screen.getByTestId('infraUnLinkDashboardMenu')).not.toBeDisabled(); - expect(screen.getByTestId('infraUnLinkDashboardMenu')).toHaveTextContent('Unlink dashboard'); - }); - it('should render the unlink dashboard action when the user cannot unlink a dashboard', () => { - jest.spyOn(hooks, 'useSavedObjectUserPermissions').mockImplementation(() => ({ - canSave: true, - canDelete: false, - })); - render( - {}} - assetType="host" - currentDashboard={TEST_CURRENT_DASHBOARD} - /> - ); - expect(screen.getByTestId('infraUnLinkDashboardMenu')).toBeDisabled(); - expect(screen.getByTestId('infraUnLinkDashboardMenu')).toHaveTextContent('Unlink dashboard'); + + describe('UnlinkDashboard', () => { + const fetchCustomDashboardsSpy = jest.spyOn(fetchCustomDashboards, 'useFetchCustomDashboards'); + + beforeEach(() => { + // provide mock for invocation to fetch custom dashboards + fetchCustomDashboardsSpy.mockReturnValue({ + dashboards: [ + { + id: 'test-so-id', + dashboardSavedObjectId: 'test-dashboard-id', + assetType: 'host', + dashboardFilterAssetIdEnabled: true, + }, + ], + loading: false, + error: null, + // @ts-expect-error we provide a mock function as we don't need to test the actual implementation + refetch: jest.fn(), + }); + }); + + afterEach(() => { + fetchCustomDashboardsSpy.mockClear(); + }); + + it('should render the unlink dashboard action when the user can unlink a dashboard', () => { + jest.spyOn(hooks, 'useSavedObjectUserPermissions').mockImplementation(() => ({ + canSave: true, + canDelete: true, + })); + render( + {}} + assetType="host" + currentDashboard={TEST_CURRENT_DASHBOARD} + /> + ); + expect(screen.getByTestId('infraUnLinkDashboardMenu')).not.toBeDisabled(); + expect(screen.getByTestId('infraUnLinkDashboardMenu')).toHaveTextContent('Unlink dashboard'); + }); + it('should render the unlink dashboard action when the user cannot unlink a dashboard', () => { + jest.spyOn(hooks, 'useSavedObjectUserPermissions').mockImplementation(() => ({ + canSave: true, + canDelete: false, + })); + render( + {}} + assetType="host" + currentDashboard={TEST_CURRENT_DASHBOARD} + /> + ); + expect(screen.getByTestId('infraUnLinkDashboardMenu')).toBeDisabled(); + expect(screen.getByTestId('infraUnLinkDashboardMenu')).toHaveTextContent('Unlink dashboard'); + }); }); }); diff --git a/x-pack/solutions/observability/plugins/investigate_app/common/rca/llm_context.ts b/x-pack/solutions/observability/plugins/investigate_app/common/rca/llm_context.ts new file mode 100644 index 0000000000000..c382026306998 --- /dev/null +++ b/x-pack/solutions/observability/plugins/investigate_app/common/rca/llm_context.ts @@ -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 { EcsFieldsResponse } from '@kbn/rule-registry-plugin/common'; +import { + ALERT_FLAPPING_HISTORY, + ALERT_RULE_EXECUTION_TIMESTAMP, + ALERT_RULE_EXECUTION_UUID, + EVENT_ACTION, + EVENT_KIND, +} from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; +import { omit } from 'lodash'; + +export function sanitizeAlert(alert: EcsFieldsResponse) { + return omit( + alert, + ALERT_RULE_EXECUTION_TIMESTAMP, + '_index', + ALERT_FLAPPING_HISTORY, + EVENT_ACTION, + EVENT_KIND, + ALERT_RULE_EXECUTION_UUID, + '@timestamp' + ); +} + +export function getRCAContext(alert: EcsFieldsResponse, serviceName: string) { + return `The user is investigating an alert for the ${serviceName} service, + and wants to find the root cause. Here is the alert: + + ${JSON.stringify(sanitizeAlert(alert))}`; +} diff --git a/x-pack/solutions/observability/plugins/investigate_app/public/pages/details/components/assistant_hypothesis/assistant_hypothesis.tsx b/x-pack/solutions/observability/plugins/investigate_app/public/pages/details/components/assistant_hypothesis/assistant_hypothesis.tsx index 57ced473922d0..9b13892b5a9ea 100644 --- a/x-pack/solutions/observability/plugins/investigate_app/public/pages/details/components/assistant_hypothesis/assistant_hypothesis.tsx +++ b/x-pack/solutions/observability/plugins/investigate_app/public/pages/details/components/assistant_hypothesis/assistant_hypothesis.tsx @@ -8,19 +8,12 @@ import { i18n } from '@kbn/i18n'; import type { RootCauseAnalysisEvent } from '@kbn/observability-ai-server/root_cause_analysis'; import { EcsFieldsResponse } from '@kbn/rule-registry-plugin/common'; -import { - ALERT_FLAPPING_HISTORY, - ALERT_RULE_EXECUTION_TIMESTAMP, - ALERT_RULE_EXECUTION_UUID, - EVENT_ACTION, - EVENT_KIND, -} from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; import { isRequestAbortedError } from '@kbn/server-route-repository-client'; -import { omit } from 'lodash'; import React, { useEffect, useRef, useState } from 'react'; import { useKibana } from '../../../../hooks/use_kibana'; import { useUpdateInvestigation } from '../../../../hooks/use_update_investigation'; import { useInvestigation } from '../../contexts/investigation_context'; +import { getRCAContext } from '../../../../../common/rca/llm_context'; export interface InvestigationContextualInsight { key: string; @@ -90,10 +83,7 @@ export function AssistantHypothesis() { body: { investigationId: investigation!.id, connectorId, - context: `The user is investigating an alert for the ${serviceName} service, - and wants to find the root cause. Here is the alert: - - ${JSON.stringify(sanitizeAlert(nonNullishAlert))}`, + context: getRCAContext(nonNullishAlert, nonNullishServiceName), rangeFrom, rangeTo, serviceName: nonNullishServiceName, @@ -190,16 +180,3 @@ export function AssistantHypothesis() { /> ); } - -function sanitizeAlert(alert: EcsFieldsResponse) { - return omit( - alert, - ALERT_RULE_EXECUTION_TIMESTAMP, - '_index', - ALERT_FLAPPING_HISTORY, - EVENT_ACTION, - EVENT_KIND, - ALERT_RULE_EXECUTION_UUID, - '@timestamp' - ); -} diff --git a/x-pack/solutions/observability/plugins/investigate_app/scripts/archive/README.md b/x-pack/solutions/observability/plugins/investigate_app/scripts/archive/README.md new file mode 100644 index 0000000000000..4f06a97699c5a --- /dev/null +++ b/x-pack/solutions/observability/plugins/investigate_app/scripts/archive/README.md @@ -0,0 +1,35 @@ +# Investigation RCA Evaluation Framework + +## Overview + +This tool is developed for our team working on the Elastic Observability platform, specifically focusing on evaluating the Investigation RCA AI Integration. It simplifies archiving data critical for evaluating the Investigation UI and it's integration with large language models (LLM). + +## Setup requirements + +- An Elasticsearch instance + +You'll need an instance configured with cross cluster search for the [edge-rca](https://studious-disco-k66oojq.pages.github.io/edge-rca/) cluster. To create one, utilize [oblt-cli](https://studious-disco-k66oojq.pages.github.io/user-guide/cluster-create-ccs/) and select `edge-rca` as the remote cluster. + +## Running archive + +Run the tool using: + +`$ node x-pack/solutions/observability/plugins/investigate_app/scripts/archive/index.js --kibana http://admin:[YOUR_CLUSTER_PASSWORD]@localhost:5601` + +This will archive the observability alerts index to use as fixtures within the tests. + +Archived data will automatically be saved at the root of the kibana project in the `.rca/archives` folder. + +## Creating a test fixture + +To create a test fixture, create a new folder in `x-pack/solutions/observability/plugins/investigate_app/scripts/load/fixtures` with the `data.json.gz` file and the `mappings.json` file. The fixture will now be loaded when running `$ node x-pack/solutions/observability/plugins/investigate_app/scripts/load/index.js` + +### Configuration + +#### Kibana and Elasticsearch + +By default, the tool will look for a Kibana instance running locally (at `http://localhost:5601`, which is the default address for running Kibana in development mode). It will also attempt to read the Kibana config file for the Elasticsearch address & credentials. If you want to override these settings, use `--kibana` and `--es`. Only basic auth is supported, e.g. `--kibana http://username:password@localhost:5601`. If you want to use a specific space, use `--spaceId` + +#### filePath + +Use `--filePath` to specify a custom file path to store your archived data. By default, data is stored at `.rca/archives` diff --git a/x-pack/solutions/observability/plugins/investigate_app/scripts/archive/archive.ts b/x-pack/solutions/observability/plugins/investigate_app/scripts/archive/archive.ts new file mode 100644 index 0000000000000..44966ffd2ad02 --- /dev/null +++ b/x-pack/solutions/observability/plugins/investigate_app/scripts/archive/archive.ts @@ -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 { spawnSync } from 'child_process'; +import { run } from '@kbn/dev-cli-runner'; +import yargs from 'yargs'; +import { getServiceUrls } from '@kbn/observability-ai-assistant-app-plugin/scripts/evaluation/get_service_urls'; +import { options } from './cli'; + +async function archiveAllRelevantData({ filePath, esUrl }: { filePath: string; esUrl: string }) { + spawnSync( + 'node', + ['scripts/es_archiver', 'save', `${filePath}/alerts`, '.internal.alerts-*', '--es-url', esUrl], + { + stdio: 'inherit', + } + ); +} + +function archiveData() { + yargs(process.argv.slice(2)) + .command('*', 'Archive RCA data', async () => { + const argv = await options(yargs); + run( + async ({ log }) => { + const serviceUrls = await getServiceUrls({ + log, + elasticsearch: argv.elasticsearch, + kibana: argv.kibana, + }); + await archiveAllRelevantData({ + esUrl: serviceUrls.esUrl, + filePath: argv.filePath, + }); + }, + { + log: { + defaultLevel: argv.logLevel as any, + }, + flags: { + allowUnexpected: true, + }, + } + ); + }) + .parse(); +} + +archiveData(); diff --git a/x-pack/solutions/observability/plugins/investigate_app/scripts/archive/cli.ts b/x-pack/solutions/observability/plugins/investigate_app/scripts/archive/cli.ts new file mode 100644 index 0000000000000..179d8ce767e7f --- /dev/null +++ b/x-pack/solutions/observability/plugins/investigate_app/scripts/archive/cli.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import * as inquirer from 'inquirer'; +import * as fs from 'fs'; +import { Argv } from 'yargs'; +import { + elasticsearchOption, + kibanaOption, +} from '@kbn/observability-ai-assistant-app-plugin/scripts/evaluation/cli'; + +function getISOStringWithoutMicroseconds(): string { + const now = new Date(); + const isoString = now.toISOString(); + return isoString.split('.')[0] + 'Z'; +} + +export async function options(y: Argv) { + const argv = y + .option('filePath', { + string: true as const, + describe: 'file path to store the archived data', + default: `./.rca/archives/${getISOStringWithoutMicroseconds()}`, + }) + .option('kibana', kibanaOption) + .option('elasticsearch', elasticsearchOption) + .option('logLevel', { + describe: 'Log level', + default: 'info', + }).argv; + + if ( + fs.existsSync(`${argv.filePath}/data.json.gz`) || + fs.existsSync(`${argv.filePath}/mappings.json`) + ) { + const { confirmOverwrite } = await inquirer.prompt([ + { + type: 'confirm', + name: 'confirmOverwrite', + message: `Archived data already exists at path: ${argv.filePath}. Do you want to overwrite it?`, + default: false, + }, + ]); + + if (!confirmOverwrite) { + process.exit(1); + } + } + + return argv; +} diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/ftr_provider_context.d.ts b/x-pack/solutions/observability/plugins/investigate_app/scripts/archive/index.js similarity index 66% rename from x-pack/solutions/observability/plugins/profiling/e2e/ftr_provider_context.d.ts rename to x-pack/solutions/observability/plugins/investigate_app/scripts/archive/index.js index 30a5f1fe518da..105baeba7af57 100644 --- a/x-pack/solutions/observability/plugins/profiling/e2e/ftr_provider_context.d.ts +++ b/x-pack/solutions/observability/plugins/investigate_app/scripts/archive/index.js @@ -5,6 +5,6 @@ * 2.0. */ -import type { GenericFtrProviderContext } from '@kbn/test'; +require('@kbn/babel-register').install(); -export type FtrProviderContext = GenericFtrProviderContext<{}, {}>; +require('./archive'); diff --git a/x-pack/solutions/observability/plugins/investigate_app/scripts/evaluate/.eslintrc.json b/x-pack/solutions/observability/plugins/investigate_app/scripts/evaluate/.eslintrc.json new file mode 100644 index 0000000000000..4eef2a5557280 --- /dev/null +++ b/x-pack/solutions/observability/plugins/investigate_app/scripts/evaluate/.eslintrc.json @@ -0,0 +1,17 @@ +{ + "overrides": [ + { + "files": [ + "**/*.spec.ts" + ], + "rules": { + "@kbn/imports/require_import": [ + "error", + "@kbn/ambient-ftr-types" + ], + "@typescript-eslint/triple-slash-reference": "off", + "spaced-comment": "off" + } + } + ] +} diff --git a/x-pack/solutions/observability/plugins/investigate_app/scripts/evaluate/README.md b/x-pack/solutions/observability/plugins/investigate_app/scripts/evaluate/README.md new file mode 100644 index 0000000000000..d83f97b39f9d6 --- /dev/null +++ b/x-pack/solutions/observability/plugins/investigate_app/scripts/evaluate/README.md @@ -0,0 +1,53 @@ +# Investigation RCA Evaluation Framework + +## Overview + +This tool is developed for our team working on the Elastic Observability platform, specifically focusing on evaluating the Investigation RCA AI Integration. It simplifies scripting and evaluating various scenarios with the Large Language Model (LLM) integration. + +## Setup requirements + +- An Elasticsearch instance configured with cross cluster search pointing to the edge-rca cluster +- A Kibana instance +- At least one .gen-ai connector set up + +## Running evaluations + +### Prerequists + +#### Elasticsearch instance + +You'll need an instance configured with cross cluster search for the [edge-rca](https://studious-disco-k66oojq.pages.github.io/edge-rca/) cluster. To create one, utilize [oblt-cli](https://studious-disco-k66oojq.pages.github.io/user-guide/cluster-create-ccs/) and select `edge-rca` as the remote cluster. + +Once your cluster is created, paste the the yml config provided in your `kibana.dev.yml` file. + +#### Fixture data + +To load the fixtures needed for the tests, first run: + +`$ node x-pack/solutions/observability/plugins/investigate_app/scripts/load/index.js --kibana http://admin:[YOUR_CLUSTER_PASSWORD]@localhost:5601` + +### Executing tests + +Run the tool using: + +`$ $ node x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/index.js --files=x-pack/solutions/observability/plugins/investigate_app/scripts/evaluate/scenarios/rca/index.spec.ts --kibana http://admin:[YOUR_CLUSTER_PASSWORD]@localhost:5601` + +This will evaluate all existing scenarios, and write the evaluation results to the terminal. + +### Configuration + +#### Kibana and Elasticsearch + +By default, the tool will look for a Kibana instance running locally (at `http://localhost:5601`, which is the default address for running Kibana in development mode). It will also attempt to read the Kibana config file for the Elasticsearch address & credentials. If you want to override these settings, use `--kibana` and `--es`. Only basic auth is supported, e.g. `--kibana http://username:password@localhost:5601`. If you want to use a specific space, use `--spaceId` + +#### Connector + +Use `--connectorId` to specify a `.gen-ai` or `.bedrock` connector to use. If none are given, it will prompt you to select a connector based on the ones that are available. If only a single supported connector is found, it will be used without prompting. + +#### Persisting conversations + +By default, completed conversations are not persisted. If you do want to persist them, for instance for reviewing purposes, set the `--persist` flag to store them. This will also generate a clickable link in the output of the evaluation that takes you to the conversation. + +If you want to clear conversations on startup, use the `--clear` flag. This only works when `--persist` is enabled. If `--spaceId` is set, only conversations for the current space will be cleared. + +When storing conversations, the name of the scenario is used as a title. Set the `--autoTitle` flag to have the LLM generate a title for you. diff --git a/x-pack/solutions/observability/plugins/investigate_app/scripts/evaluate/rca_client.ts b/x-pack/solutions/observability/plugins/investigate_app/scripts/evaluate/rca_client.ts new file mode 100644 index 0000000000000..c6187d8e418c3 --- /dev/null +++ b/x-pack/solutions/observability/plugins/investigate_app/scripts/evaluate/rca_client.ts @@ -0,0 +1,174 @@ +/* + * 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 { Readable } from 'stream'; +import { AxiosResponse } from 'axios'; +import { v4 as uuidv4 } from 'uuid'; +import datemath from '@kbn/datemath'; +import { ToolingLog } from '@kbn/tooling-log'; +import { CreateInvestigationResponse } from '@kbn/investigation-shared'; +import type { EcsFieldsResponse } from '@kbn/rule-registry-plugin/common'; +import { httpResponseIntoObservable } from '@kbn/sse-utils-client'; +import { defer, lastValueFrom, toArray } from 'rxjs'; +import { KibanaClient } from '@kbn/observability-ai-assistant-app-plugin/scripts/evaluation/kibana_client'; +import type { RootCauseAnalysisEvent } from '@kbn/observability-ai-server/root_cause_analysis'; +import { getRCAContext } from '../../common/rca/llm_context'; + +export class RCAClient { + constructor(protected readonly kibanaClient: KibanaClient, protected readonly log: ToolingLog) {} + + async getAlert(alertId: string): Promise { + const response = await this.kibanaClient.callKibana('get', { + pathname: '/internal/rac/alerts', + query: { + id: alertId, + }, + }); + return response.data; + } + + async getTimeRange({ + fromOffset = 'now-15m', + toOffset = 'now+15m', + alert, + }: { + fromOffset: string; + toOffset: string; + alert: EcsFieldsResponse; + }) { + const alertStart = alert['kibana.alert.start'] as string | undefined; + if (!alertStart) { + throw new Error( + 'Alert start time is missing from the alert data. Please double check your alert fixture.' + ); + } + const from = datemath.parse(fromOffset, { forceNow: new Date(alertStart) })?.valueOf()!; + const to = datemath.parse(toOffset, { forceNow: new Date(alertStart) })?.valueOf()!; + return { + from, + to, + }; + } + + async createInvestigation({ + alertId, + from, + to, + }: { + alertId: string; + from: number; + to: number; + }): Promise { + const body = { + id: uuidv4(), + title: 'Investigate Custom threshold breached', + params: { + timeRange: { + from, + to, + }, + }, + tags: [], + origin: { + type: 'alert', + id: alertId, + }, + externalIncidentUrl: null, + }; + + const response = await this.kibanaClient.callKibana( + 'post', + { + pathname: '/api/observability/investigations', + }, + body + ); + + return response.data.id; + } + + async deleteInvestigation({ investigationId }: { investigationId: string }): Promise { + await this.kibanaClient.callKibana('delete', { + pathname: `/api/observability/investigations/${investigationId}`, + }); + } + + async rootCauseAnalysis({ + connectorId, + investigationId, + from, + to, + alert, + }: { + connectorId: string; + investigationId: string; + from: string; + to: string; + alert?: EcsFieldsResponse; + }) { + this.log.debug(`Calling root cause analysis API`); + const that = this; + const serviceName = alert?.['service.name'] as string | undefined; + if (!alert) { + throw new Error( + 'Alert not found. Please ensure you have loaded test fixture data prior to running tests.' + ); + } + if (!serviceName) { + throw new Error( + 'Service name is missing from the alert data. Please double check your alert fixture.' + ); + } + const context = getRCAContext(alert, serviceName); + const body = { + investigationId, + connectorId, + context, + rangeFrom: from, + rangeTo: to, + serviceName: 'controller', + completeInBackground: false, + }; + + const chat$ = defer(async () => { + const response: AxiosResponse = await this.kibanaClient.callKibana( + 'post', + { + pathname: '/internal/observability/investigation/root_cause_analysis', + }, + body, + { responseType: 'stream', timeout: NaN } + ); + + return { + response: { + body: new ReadableStream({ + start(controller) { + response.data.on('data', (chunk: Buffer) => { + that.log.info(`Analyzing root cause...`); + controller.enqueue(chunk); + }); + + response.data.on('end', () => { + that.log.info(`Root cause analysis completed`); + controller.close(); + }); + + response.data.on('error', (err: Error) => { + that.log.error(`Error while analyzing root cause: ${err}`); + controller.error(err); + }); + }, + }), + }, + }; + }).pipe(httpResponseIntoObservable(), toArray()); + + const events = await lastValueFrom(chat$); + + return events.map((event) => event.event) as RootCauseAnalysisEvent[]; + } +} diff --git a/x-pack/solutions/observability/plugins/investigate_app/scripts/evaluate/scenarios/rca/index.spec.ts b/x-pack/solutions/observability/plugins/investigate_app/scripts/evaluate/scenarios/rca/index.spec.ts new file mode 100644 index 0000000000000..1a6ecea09f3b9 --- /dev/null +++ b/x-pack/solutions/observability/plugins/investigate_app/scripts/evaluate/scenarios/rca/index.spec.ts @@ -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 type { + RootCauseAnalysisEvent, + EndProcessToolMessage, + InvestigateEntityToolMessage, + ObservationToolMessage, + ToolErrorMessage, +} from '@kbn/observability-ai-server/root_cause_analysis'; +import { + chatClient, + kibanaClient, + logger, +} from '@kbn/observability-ai-assistant-app-plugin/scripts/evaluation/services'; +import { RCAClient } from '../../rca_client'; + +type ToolCallMessage = + | EndProcessToolMessage + | InvestigateEntityToolMessage + | ObservationToolMessage + | ToolErrorMessage; + +const ALERT_FIXTURE_ID = '0265d890-8d8d-4c7e-a5bd-a3951f79574e'; + +describe('Root cause analysis', () => { + const investigations: string[] = []; + const rcaChatClient = new RCAClient(kibanaClient, logger); + function countEntities(entities: InvestigateEntityToolMessage[]) { + const entityCount: Record = {}; + entities.forEach((entity) => { + const name = entity.response.entity['service.name']; + entityCount[name] = (entityCount[name] || 0) + 1; + }); + return entityCount; + } + + function categorizeEvents(events: RootCauseAnalysisEvent[]) { + const report: EndProcessToolMessage[] = []; + const observations: ObservationToolMessage[] = []; + const errors: ToolErrorMessage[] = []; + const entities: InvestigateEntityToolMessage[] = []; + const other: RootCauseAnalysisEvent[] = []; + const toolCallEvents = events.filter((event): event is ToolCallMessage => { + const maybeToolEvent = event as EndProcessToolMessage; + return ( + maybeToolEvent?.name === 'endProcessAndWriteReport' || + maybeToolEvent?.name === 'observe' || + maybeToolEvent?.name === 'error' || + maybeToolEvent?.name === 'investigateEntity' + ); + }); + toolCallEvents.forEach((event) => { + if (event.name) { + switch (event.name) { + case 'endProcessAndWriteReport': + report.push(event as EndProcessToolMessage); + break; + case 'observe': + observations.push(event as ObservationToolMessage); + break; + case 'error': + errors.push(event as ToolErrorMessage); + break; + case 'investigateEntity': + entities.push(event as InvestigateEntityToolMessage); + break; + default: + other.push(event); + } + } + }); + if (report.length > 1) { + throw new Error('More than one final report found'); + } + if (report.length === 0) { + throw new Error('No final report found'); + } + return { report: report[0], observations, errors, entities, other }; + } + + it('can accurately pinpoint the root cause of cartservice bad entrypoint failure', async () => { + const alert = await rcaChatClient.getAlert(ALERT_FIXTURE_ID); + const connectorId = chatClient.getConnectorId(); + const { from, to } = await rcaChatClient.getTimeRange({ + fromOffset: 'now-15m', + toOffset: 'now+15m', + alert, + }); + const investigationId = await rcaChatClient.createInvestigation({ + alertId: ALERT_FIXTURE_ID, + from, + to, + }); + investigations.push(investigationId); + const events = await rcaChatClient.rootCauseAnalysis({ + investigationId, + from: new Date(from).toISOString(), + to: new Date(to).toISOString(), + alert, + connectorId, + }); + const { report, entities, errors } = categorizeEvents(events); + const prompt = ` + An investigation was performed by the Observability AI Assistant to identify the root cause of an alert for the controller service. Here is the alert: + + ${JSON.stringify(alert)} + + The following entities were analyzed during the investigation. + ${Object.entries(countEntities(entities)) + .map(([name, count]) => { + return ` - ${name} (analyzed ${count} times)`; + }) + .join('\n')} + + During the course of the investigation, the Observability AI Assistant encountered ${ + errors.length + } errors when attempting to analyze the entities.${ + errors.length + ? ' These errors were failures to retrieve data from the entities and do not reflect issues in the system being evaluated' + : '' + }. + + A report was written by the Observability AI Assistant detailing issues throughout the system, including the controller service and it's dependencies. The report includes a hypothesis about the underlying root cause of the system failure. Here is the report: + + ${report.response.report} + `; + + const conversation = await chatClient.complete({ messages: prompt }); + + await chatClient.evaluate(conversation, [ + 'Effectively reflects the actual root cause in the report. The actual root cause of the system failure was a misconfiguration related to the `cartservice`. A bad container entrypoint was configured for the cart service, causing it to fail to start', + 'Analyzes the cartservice during the course of the investigation.', + 'Analyzes each entity only once.', + 'The Observability AI Assistant encountered 0 errors when attempting to analyze the system failure.', + ]); + }); + + after(async () => { + for (const investigationId of investigations) { + await rcaChatClient.deleteInvestigation({ investigationId }); + } + }); +}); diff --git a/x-pack/solutions/observability/plugins/investigate_app/scripts/load/README.md b/x-pack/solutions/observability/plugins/investigate_app/scripts/load/README.md new file mode 100644 index 0000000000000..de4452c036612 --- /dev/null +++ b/x-pack/solutions/observability/plugins/investigate_app/scripts/load/README.md @@ -0,0 +1,25 @@ +# Investigation RCA Evaluation Framework + +## Overview + +This tool is developed for our team working on the Elastic Observability platform, specifically focusing on evaluating the Investigation RCA AI Integration. It simplifies archiving data critical for evaluating the Investigation UI and it's integration with large language models (LLM). + +## Setup requirements + +- An Elasticsearch instance + +You'll need an instance configured with cross cluster search for the [edge-rca](https://studious-disco-k66oojq.pages.github.io/edge-rca/) cluster. To create one, utilize [oblt-cli](https://studious-disco-k66oojq.pages.github.io/user-guide/cluster-create-ccs/) and select `edge-rca` as the remote cluster. + +## Running archive + +Run the tool using: + +`$ node x-pack/solutions/observability/plugins/investigate_app/scripts/load/index.js --kibana http://admin:[YOUR_CLUSTER_PASSWORD]@localhost:5601` + +This will load all fixtures located in `./fixtures`. + +### Configuration + +#### Kibana and Elasticsearch + +By default, the tool will look for a Kibana instance running locally (at `http://localhost:5601`, which is the default address for running Kibana in development mode). It will also attempt to read the Kibana config file for the Elasticsearch address & credentials. If you want to override these settings, use `--kibana` and `--es`. Only basic auth is supported, e.g. `--kibana http://username:password@localhost:5601`. If you want to use a specific space, use `--spaceId` diff --git a/x-pack/solutions/observability/plugins/investigate_app/scripts/load/cli.ts b/x-pack/solutions/observability/plugins/investigate_app/scripts/load/cli.ts new file mode 100644 index 0000000000000..61e0235a439fa --- /dev/null +++ b/x-pack/solutions/observability/plugins/investigate_app/scripts/load/cli.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 { Argv } from 'yargs'; +import { + elasticsearchOption, + kibanaOption, +} from '@kbn/observability-ai-assistant-app-plugin/scripts/evaluation/cli'; + +export async function options(y: Argv) { + const argv = y + .option('kibana', kibanaOption) + .option('elasticsearch', elasticsearchOption) + .option('logLevel', { + describe: 'Log level', + default: 'info', + }).argv; + + return argv; +} diff --git a/x-pack/solutions/observability/plugins/investigate_app/scripts/load/fixtures/custom_threshold_alerts/data.json.gz b/x-pack/solutions/observability/plugins/investigate_app/scripts/load/fixtures/custom_threshold_alerts/data.json.gz new file mode 100644 index 0000000000000..df19f47f804b2 Binary files /dev/null and b/x-pack/solutions/observability/plugins/investigate_app/scripts/load/fixtures/custom_threshold_alerts/data.json.gz differ diff --git a/x-pack/solutions/observability/plugins/investigate_app/scripts/load/fixtures/custom_threshold_alerts/mappings.json b/x-pack/solutions/observability/plugins/investigate_app/scripts/load/fixtures/custom_threshold_alerts/mappings.json new file mode 100644 index 0000000000000..99d57716fe7b6 --- /dev/null +++ b/x-pack/solutions/observability/plugins/investigate_app/scripts/load/fixtures/custom_threshold_alerts/mappings.json @@ -0,0 +1,33106 @@ +{ + "type": "index", + "value": { + "aliases": { + ".alerts-observability.apm.alerts-default": { + "is_write_index": true + } + }, + "index": ".internal.alerts-observability.apm.alerts-default-000001", + "mappings": { + "_meta": { + "kibana": { + "version": "9.0.0" + }, + "managed": true, + "namespace": "default" + }, + "dynamic": "false", + "properties": { + "@timestamp": { + "ignore_malformed": false, + "type": "date" + }, + "agent": { + "properties": { + "name": { + "type": "keyword" + } + } + }, + "container": { + "properties": { + "id": { + "type": "keyword" + } + } + }, + "ecs": { + "properties": { + "version": { + "type": "keyword" + } + } + }, + "error": { + "properties": { + "grouping_key": { + "type": "keyword" + }, + "grouping_name": { + "type": "keyword" + } + } + }, + "event": { + "properties": { + "action": { + "ignore_above": 1024, + "type": "keyword" + }, + "kind": { + "ignore_above": 1024, + "type": "keyword" + }, + "original": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "host": { + "properties": { + "name": { + "type": "keyword" + } + } + }, + "kibana": { + "properties": { + "alert": { + "properties": { + "action_group": { + "type": "keyword" + }, + "case_ids": { + "type": "keyword" + }, + "consecutive_matches": { + "type": "long" + }, + "context": { + "type": "object" + }, + "duration": { + "properties": { + "us": { + "type": "long" + } + } + }, + "end": { + "type": "date" + }, + "evaluation": { + "properties": { + "threshold": { + "scaling_factor": 100, + "type": "scaled_float" + }, + "value": { + "scaling_factor": 100, + "type": "scaled_float" + }, + "values": { + "scaling_factor": 100, + "type": "scaled_float" + } + } + }, + "flapping": { + "type": "boolean" + }, + "flapping_history": { + "type": "boolean" + }, + "group": { + "properties": { + "field": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + }, + "instance": { + "properties": { + "id": { + "type": "keyword" + } + } + }, + "intended_timestamp": { + "type": "date" + }, + "last_detected": { + "type": "date" + }, + "maintenance_window_ids": { + "type": "keyword" + }, + "previous_action_group": { + "type": "keyword" + }, + "reason": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "keyword" + }, + "risk_score": { + "type": "float" + }, + "rule": { + "properties": { + "author": { + "type": "keyword" + }, + "category": { + "type": "keyword" + }, + "consumer": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "type": "keyword" + }, + "description": { + "type": "keyword" + }, + "enabled": { + "type": "keyword" + }, + "execution": { + "properties": { + "timestamp": { + "type": "date" + }, + "type": { + "type": "keyword" + }, + "uuid": { + "type": "keyword" + } + } + }, + "from": { + "type": "keyword" + }, + "interval": { + "type": "keyword" + }, + "license": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "note": { + "type": "keyword" + }, + "parameters": { + "ignore_above": 4096, + "type": "flattened" + }, + "producer": { + "type": "keyword" + }, + "references": { + "type": "keyword" + }, + "revision": { + "type": "long" + }, + "rule_id": { + "type": "keyword" + }, + "rule_name_override": { + "type": "keyword" + }, + "rule_type_id": { + "type": "keyword" + }, + "tags": { + "type": "keyword" + }, + "to": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "type": "keyword" + }, + "uuid": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + } + }, + "severity": { + "type": "keyword" + }, + "severity_improving": { + "type": "boolean" + }, + "start": { + "type": "date" + }, + "status": { + "type": "keyword" + }, + "suppression": { + "properties": { + "docs_count": { + "type": "long" + }, + "end": { + "type": "date" + }, + "start": { + "type": "date" + }, + "terms": { + "properties": { + "field": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + } + } + }, + "system_status": { + "type": "keyword" + }, + "time_range": { + "format": "epoch_millis||strict_date_optional_time", + "type": "date_range" + }, + "url": { + "ignore_above": 2048, + "index": false, + "type": "keyword" + }, + "uuid": { + "type": "keyword" + }, + "workflow_assignee_ids": { + "type": "keyword" + }, + "workflow_reason": { + "type": "keyword" + }, + "workflow_status": { + "type": "keyword" + }, + "workflow_status_updated_at": { + "type": "date" + }, + "workflow_tags": { + "type": "keyword" + }, + "workflow_user": { + "type": "keyword" + } + } + }, + "space_ids": { + "type": "keyword" + }, + "version": { + "type": "version" + } + } + }, + "labels": { + "dynamic": "true", + "type": "object" + }, + "processor": { + "properties": { + "event": { + "type": "keyword" + } + } + }, + "service": { + "properties": { + "environment": { + "type": "keyword" + }, + "language": { + "properties": { + "name": { + "type": "keyword" + } + } + }, + "name": { + "type": "keyword" + } + } + }, + "tags": { + "type": "keyword" + }, + "transaction": { + "properties": { + "name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + } + } + }, + "settings": { + "index": { + "auto_expand_replicas": "0-1", + "hidden": "true", + "lifecycle": { + "name": ".alerts-ilm-policy", + "rollover_alias": ".alerts-observability.apm.alerts-default" + }, + "mapping": { + "ignore_malformed": "true", + "total_fields": { + "limit": "2500" + } + }, + "number_of_replicas": "1", + "number_of_shards": "1" + } + } + } +} + +{ + "type": "index", + "value": { + "aliases": { + ".alerts-observability.logs.alerts-default": { + "is_write_index": true + } + }, + "index": ".internal.alerts-observability.logs.alerts-default-000001", + "mappings": { + "_meta": { + "kibana": { + "version": "9.0.0" + }, + "managed": true, + "namespace": "default" + }, + "dynamic": "false", + "properties": { + "@timestamp": { + "ignore_malformed": false, + "type": "date" + }, + "agent": { + "properties": { + "build": { + "properties": { + "original": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "client": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "cloud": { + "properties": { + "account": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "instance": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "machine": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "origin": { + "properties": { + "account": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "instance": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "machine": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "project": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "region": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "project": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "region": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "target": { + "properties": { + "account": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "instance": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "machine": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "project": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "region": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "container": { + "properties": { + "cpu": { + "properties": { + "usage": { + "scaling_factor": 1000, + "type": "scaled_float" + } + } + }, + "disk": { + "properties": { + "read": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "write": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "image": { + "properties": { + "hash": { + "properties": { + "all": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "tag": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "labels": { + "type": "object" + }, + "memory": { + "properties": { + "usage": { + "scaling_factor": 1000, + "type": "scaled_float" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "network": { + "properties": { + "egress": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "ingress": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "runtime": { + "ignore_above": 1024, + "type": "keyword" + }, + "security_context": { + "properties": { + "privileged": { + "type": "boolean" + } + } + } + } + }, + "destination": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "device": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "manufacturer": { + "ignore_above": 1024, + "type": "keyword" + }, + "model": { + "properties": { + "identifier": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "dll": { + "properties": { + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + } + } + }, + "dns": { + "properties": { + "answers": { + "properties": { + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "ttl": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "header_flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "op_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "question": { + "properties": { + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "resolved_ip": { + "type": "ip" + }, + "response_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ecs": { + "properties": { + "version": { + "type": "keyword" + } + } + }, + "email": { + "properties": { + "attachments": { + "properties": { + "file": { + "properties": { + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "size": { + "type": "long" + } + } + } + }, + "type": "nested" + }, + "bcc": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "cc": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "content_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "delivery_timestamp": { + "type": "date" + }, + "direction": { + "ignore_above": 1024, + "type": "keyword" + }, + "from": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "local_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "message_id": { + "type": "wildcard" + }, + "origination_timestamp": { + "type": "date" + }, + "reply_to": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "sender": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "subject": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "to": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "x_mailer": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "error": { + "properties": { + "code": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "message": { + "type": "match_only_text" + }, + "stack_trace": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "event": { + "properties": { + "action": { + "ignore_above": 1024, + "type": "keyword" + }, + "agent_id_status": { + "ignore_above": 1024, + "type": "keyword" + }, + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "code": { + "ignore_above": 1024, + "type": "keyword" + }, + "created": { + "type": "date" + }, + "dataset": { + "ignore_above": 1024, + "type": "keyword" + }, + "duration": { + "type": "long" + }, + "end": { + "type": "date" + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ingested": { + "type": "date" + }, + "kind": { + "ignore_above": 1024, + "type": "keyword" + }, + "module": { + "ignore_above": 1024, + "type": "keyword" + }, + "original": { + "ignore_above": 1024, + "type": "keyword" + }, + "outcome": { + "ignore_above": 1024, + "type": "keyword" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "reason": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "risk_score": { + "type": "float" + }, + "risk_score_norm": { + "type": "float" + }, + "sequence": { + "type": "long" + }, + "severity": { + "type": "long" + }, + "start": { + "type": "date" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "faas": { + "properties": { + "coldstart": { + "type": "boolean" + }, + "execution": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "ignore_above": 1024, + "type": "keyword" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "drive_letter": { + "ignore_above": 1, + "type": "keyword" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fork_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "macho": { + "properties": { + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "symhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "host": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "boot": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "cpu": { + "properties": { + "usage": { + "scaling_factor": 1000, + "type": "scaled_float" + } + } + }, + "disk": { + "properties": { + "read": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "write": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "network": { + "properties": { + "egress": { + "properties": { + "bytes": { + "type": "long" + }, + "packets": { + "type": "long" + } + } + }, + "ingress": { + "properties": { + "bytes": { + "type": "long" + }, + "packets": { + "type": "long" + } + } + } + } + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pid_ns_ino": { + "ignore_above": 1024, + "type": "keyword" + }, + "risk": { + "properties": { + "calculated_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "calculated_score": { + "type": "float" + }, + "calculated_score_norm": { + "type": "float" + }, + "static_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "static_score": { + "type": "float" + }, + "static_score_norm": { + "type": "float" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uptime": { + "type": "long" + } + } + }, + "http": { + "properties": { + "request": { + "properties": { + "body": { + "properties": { + "bytes": { + "type": "long" + }, + "content": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + } + } + }, + "bytes": { + "type": "long" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "method": { + "ignore_above": 1024, + "type": "keyword" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "referrer": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "response": { + "properties": { + "body": { + "properties": { + "bytes": { + "type": "long" + }, + "content": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + } + } + }, + "bytes": { + "type": "long" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "status_code": { + "type": "long" + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "kibana": { + "properties": { + "alert": { + "properties": { + "action_group": { + "type": "keyword" + }, + "case_ids": { + "type": "keyword" + }, + "consecutive_matches": { + "type": "long" + }, + "context": { + "type": "object" + }, + "duration": { + "properties": { + "us": { + "type": "long" + } + } + }, + "end": { + "type": "date" + }, + "evaluation": { + "properties": { + "threshold": { + "scaling_factor": 100, + "type": "scaled_float" + }, + "value": { + "scaling_factor": 100, + "type": "scaled_float" + }, + "values": { + "scaling_factor": 100, + "type": "scaled_float" + } + } + }, + "flapping": { + "type": "boolean" + }, + "flapping_history": { + "type": "boolean" + }, + "group": { + "properties": { + "field": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + }, + "instance": { + "properties": { + "id": { + "type": "keyword" + } + } + }, + "intended_timestamp": { + "type": "date" + }, + "last_detected": { + "type": "date" + }, + "maintenance_window_ids": { + "type": "keyword" + }, + "previous_action_group": { + "type": "keyword" + }, + "reason": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "keyword" + }, + "risk_score": { + "type": "float" + }, + "rule": { + "properties": { + "author": { + "type": "keyword" + }, + "category": { + "type": "keyword" + }, + "consumer": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "type": "keyword" + }, + "description": { + "type": "keyword" + }, + "enabled": { + "type": "keyword" + }, + "execution": { + "properties": { + "timestamp": { + "type": "date" + }, + "type": { + "type": "keyword" + }, + "uuid": { + "type": "keyword" + } + } + }, + "from": { + "type": "keyword" + }, + "interval": { + "type": "keyword" + }, + "license": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "note": { + "type": "keyword" + }, + "parameters": { + "ignore_above": 4096, + "type": "flattened" + }, + "producer": { + "type": "keyword" + }, + "references": { + "type": "keyword" + }, + "revision": { + "type": "long" + }, + "rule_id": { + "type": "keyword" + }, + "rule_name_override": { + "type": "keyword" + }, + "rule_type_id": { + "type": "keyword" + }, + "tags": { + "type": "keyword" + }, + "to": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "type": "keyword" + }, + "uuid": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + } + }, + "severity": { + "type": "keyword" + }, + "severity_improving": { + "type": "boolean" + }, + "start": { + "type": "date" + }, + "status": { + "type": "keyword" + }, + "suppression": { + "properties": { + "docs_count": { + "type": "long" + }, + "end": { + "type": "date" + }, + "start": { + "type": "date" + }, + "terms": { + "properties": { + "field": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + } + } + }, + "system_status": { + "type": "keyword" + }, + "time_range": { + "format": "epoch_millis||strict_date_optional_time", + "type": "date_range" + }, + "url": { + "ignore_above": 2048, + "index": false, + "type": "keyword" + }, + "uuid": { + "type": "keyword" + }, + "workflow_assignee_ids": { + "type": "keyword" + }, + "workflow_reason": { + "type": "keyword" + }, + "workflow_status": { + "type": "keyword" + }, + "workflow_status_updated_at": { + "type": "date" + }, + "workflow_tags": { + "type": "keyword" + }, + "workflow_user": { + "type": "keyword" + } + } + }, + "space_ids": { + "type": "keyword" + }, + "version": { + "type": "version" + } + } + }, + "labels": { + "type": "object" + }, + "log": { + "properties": { + "file": { + "properties": { + "path": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "level": { + "ignore_above": 1024, + "type": "keyword" + }, + "logger": { + "ignore_above": 1024, + "type": "keyword" + }, + "origin": { + "properties": { + "file": { + "properties": { + "line": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "function": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "syslog": { + "properties": { + "appname": { + "ignore_above": 1024, + "type": "keyword" + }, + "facility": { + "properties": { + "code": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "msgid": { + "ignore_above": 1024, + "type": "keyword" + }, + "priority": { + "type": "long" + }, + "procid": { + "ignore_above": 1024, + "type": "keyword" + }, + "severity": { + "properties": { + "code": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "structured_data": { + "type": "flattened" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "message": { + "type": "match_only_text" + }, + "network": { + "properties": { + "application": { + "ignore_above": 1024, + "type": "keyword" + }, + "bytes": { + "type": "long" + }, + "community_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "direction": { + "ignore_above": 1024, + "type": "keyword" + }, + "forwarded_ip": { + "type": "ip" + }, + "iana_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "inner": { + "properties": { + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "packets": { + "type": "long" + }, + "protocol": { + "ignore_above": 1024, + "type": "keyword" + }, + "transport": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "observer": { + "properties": { + "egress": { + "properties": { + "interface": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "zone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "ingress": { + "properties": { + "interface": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "zone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "vendor": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "orchestrator": { + "properties": { + "api_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "cluster": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "namespace": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "resource": { + "properties": { + "annotation": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "label": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "organization": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "package": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "build_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "checksum": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "install_scope": { + "ignore_above": 1024, + "type": "keyword" + }, + "installed": { + "type": "date" + }, + "license": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "process": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "end": { + "type": "date" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "entry_leader": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "attested_groups": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "attested_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "entry_meta": { + "properties": { + "source": { + "properties": { + "ip": { + "type": "ip" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "session_leader": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "same_as_process": { + "type": "boolean" + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "env_vars": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "group_leader": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "same_as_process": { + "type": "boolean" + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "io": { + "properties": { + "bytes_skipped": { + "properties": { + "length": { + "type": "long" + }, + "offset": { + "type": "long" + } + } + }, + "max_bytes_per_process_exceeded": { + "type": "boolean" + }, + "text": { + "type": "wildcard" + }, + "total_bytes_captured": { + "type": "long" + }, + "total_bytes_skipped": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "macho": { + "properties": { + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "symhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "end": { + "type": "date" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "group_leader": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "macho": { + "properties": { + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "symhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "thread": { + "properties": { + "capabilities": { + "properties": { + "effective": { + "ignore_above": 1024, + "type": "keyword" + }, + "permitted": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "title": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "uptime": { + "type": "long" + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "previous": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "session_leader": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "session_leader": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "same_as_process": { + "type": "boolean" + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "thread": { + "properties": { + "capabilities": { + "properties": { + "effective": { + "ignore_above": 1024, + "type": "keyword" + }, + "permitted": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "title": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + }, + "columns": { + "type": "long" + }, + "rows": { + "type": "long" + } + } + }, + "uptime": { + "type": "long" + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "strings": { + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hive": { + "ignore_above": 1024, + "type": "keyword" + }, + "key": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "value": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "related": { + "properties": { + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "hosts": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "user": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "rule": { + "properties": { + "author": { + "ignore_above": 1024, + "type": "keyword" + }, + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "license": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "ruleset": { + "ignore_above": 1024, + "type": "keyword" + }, + "uuid": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "server": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "service": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "environment": { + "ignore_above": 1024, + "type": "keyword" + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "node": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "role": { + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "origin": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "environment": { + "ignore_above": 1024, + "type": "keyword" + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "node": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "role": { + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "state": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "state": { + "ignore_above": 1024, + "type": "keyword" + }, + "target": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "environment": { + "ignore_above": 1024, + "type": "keyword" + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "node": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "role": { + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "state": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "source": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "span": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tags": { + "type": "keyword" + }, + "threat": { + "properties": { + "enrichments": { + "properties": { + "indicator": { + "properties": { + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "confidence": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "ignore_above": 1024, + "type": "keyword" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "drive_letter": { + "ignore_above": 1, + "type": "keyword" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fork_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "first_seen": { + "type": "date" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "last_seen": { + "type": "date" + }, + "marking": { + "properties": { + "tlp": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlp_version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "modified_at": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "port": { + "type": "long" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "strings": { + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hive": { + "ignore_above": 1024, + "type": "keyword" + }, + "key": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "value": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "scanner_stats": { + "type": "long" + }, + "sightings": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fragment": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "password": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "type": "wildcard" + }, + "port": { + "type": "long" + }, + "query": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "scheme": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "username": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "matched": { + "properties": { + "atomic": { + "ignore_above": 1024, + "type": "keyword" + }, + "field": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "index": { + "ignore_above": 1024, + "type": "keyword" + }, + "occurred": { + "type": "date" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + }, + "type": "nested" + }, + "feed": { + "properties": { + "dashboard_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "framework": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "indicator": { + "properties": { + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "confidence": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "ignore_above": 1024, + "type": "keyword" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "drive_letter": { + "ignore_above": 1, + "type": "keyword" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fork_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "first_seen": { + "type": "date" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "last_seen": { + "type": "date" + }, + "marking": { + "properties": { + "tlp": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlp_version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "modified_at": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "port": { + "type": "long" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "strings": { + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hive": { + "ignore_above": 1024, + "type": "keyword" + }, + "key": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "value": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "scanner_stats": { + "type": "long" + }, + "sightings": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fragment": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "password": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "type": "wildcard" + }, + "port": { + "type": "long" + }, + "query": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "scheme": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "username": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "software": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "platforms": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tactic": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "technique": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "subtechnique": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "tls": { + "properties": { + "cipher": { + "ignore_above": 1024, + "type": "keyword" + }, + "client": { + "properties": { + "certificate": { + "ignore_above": 1024, + "type": "keyword" + }, + "certificate_chain": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "issuer": { + "ignore_above": 1024, + "type": "keyword" + }, + "ja3": { + "ignore_above": 1024, + "type": "keyword" + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "server_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "ignore_above": 1024, + "type": "keyword" + }, + "supported_ciphers": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "established": { + "type": "boolean" + }, + "next_protocol": { + "ignore_above": 1024, + "type": "keyword" + }, + "resumed": { + "type": "boolean" + }, + "server": { + "properties": { + "certificate": { + "ignore_above": 1024, + "type": "keyword" + }, + "certificate_chain": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "issuer": { + "ignore_above": 1024, + "type": "keyword" + }, + "ja3s": { + "ignore_above": 1024, + "type": "keyword" + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "subject": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + }, + "version_protocol": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "trace": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "transaction": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "url": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fragment": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "password": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "type": "wildcard" + }, + "port": { + "type": "long" + }, + "query": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "scheme": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "username": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "user": { + "properties": { + "changes": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "effective": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "risk": { + "properties": { + "calculated_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "calculated_score": { + "type": "float" + }, + "calculated_score_norm": { + "type": "float" + }, + "static_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "static_score": { + "type": "float" + }, + "static_score_norm": { + "type": "float" + } + } + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + }, + "target": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "user_agent": { + "properties": { + "device": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vulnerability": { + "properties": { + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "classification": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "enumeration": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "report_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "scanner": { + "properties": { + "vendor": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "score": { + "properties": { + "base": { + "type": "float" + }, + "environmental": { + "type": "float" + }, + "temporal": { + "type": "float" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "severity": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "settings": { + "index": { + "auto_expand_replicas": "0-1", + "hidden": "true", + "lifecycle": { + "name": ".alerts-ilm-policy", + "rollover_alias": ".alerts-observability.logs.alerts-default" + }, + "mapping": { + "ignore_malformed": "true", + "total_fields": { + "limit": "2500" + } + }, + "number_of_replicas": "1", + "number_of_shards": "1" + } + } + } +} + +{ + "type": "index", + "value": { + "aliases": { + ".alerts-observability.metrics.alerts-default": { + "is_write_index": true + } + }, + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "mappings": { + "_meta": { + "kibana": { + "version": "9.0.0" + }, + "managed": true, + "namespace": "default" + }, + "dynamic": "false", + "properties": { + "@timestamp": { + "ignore_malformed": false, + "type": "date" + }, + "agent": { + "properties": { + "build": { + "properties": { + "original": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "client": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "cloud": { + "properties": { + "account": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "instance": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "machine": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "origin": { + "properties": { + "account": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "instance": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "machine": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "project": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "region": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "project": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "region": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "target": { + "properties": { + "account": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "instance": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "machine": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "project": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "region": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "container": { + "properties": { + "cpu": { + "properties": { + "usage": { + "scaling_factor": 1000, + "type": "scaled_float" + } + } + }, + "disk": { + "properties": { + "read": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "write": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "image": { + "properties": { + "hash": { + "properties": { + "all": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "tag": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "labels": { + "type": "object" + }, + "memory": { + "properties": { + "usage": { + "scaling_factor": 1000, + "type": "scaled_float" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "network": { + "properties": { + "egress": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "ingress": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "runtime": { + "ignore_above": 1024, + "type": "keyword" + }, + "security_context": { + "properties": { + "privileged": { + "type": "boolean" + } + } + } + } + }, + "destination": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "device": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "manufacturer": { + "ignore_above": 1024, + "type": "keyword" + }, + "model": { + "properties": { + "identifier": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "dll": { + "properties": { + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + } + } + }, + "dns": { + "properties": { + "answers": { + "properties": { + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "ttl": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "header_flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "op_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "question": { + "properties": { + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "resolved_ip": { + "type": "ip" + }, + "response_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ecs": { + "properties": { + "version": { + "type": "keyword" + } + } + }, + "email": { + "properties": { + "attachments": { + "properties": { + "file": { + "properties": { + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "size": { + "type": "long" + } + } + } + }, + "type": "nested" + }, + "bcc": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "cc": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "content_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "delivery_timestamp": { + "type": "date" + }, + "direction": { + "ignore_above": 1024, + "type": "keyword" + }, + "from": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "local_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "message_id": { + "type": "wildcard" + }, + "origination_timestamp": { + "type": "date" + }, + "reply_to": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "sender": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "subject": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "to": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "x_mailer": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "error": { + "properties": { + "code": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "message": { + "type": "match_only_text" + }, + "stack_trace": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "event": { + "properties": { + "action": { + "ignore_above": 1024, + "type": "keyword" + }, + "agent_id_status": { + "ignore_above": 1024, + "type": "keyword" + }, + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "code": { + "ignore_above": 1024, + "type": "keyword" + }, + "created": { + "type": "date" + }, + "dataset": { + "ignore_above": 1024, + "type": "keyword" + }, + "duration": { + "type": "long" + }, + "end": { + "type": "date" + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ingested": { + "type": "date" + }, + "kind": { + "ignore_above": 1024, + "type": "keyword" + }, + "module": { + "ignore_above": 1024, + "type": "keyword" + }, + "original": { + "ignore_above": 1024, + "type": "keyword" + }, + "outcome": { + "ignore_above": 1024, + "type": "keyword" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "reason": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "risk_score": { + "type": "float" + }, + "risk_score_norm": { + "type": "float" + }, + "sequence": { + "type": "long" + }, + "severity": { + "type": "long" + }, + "start": { + "type": "date" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "faas": { + "properties": { + "coldstart": { + "type": "boolean" + }, + "execution": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "ignore_above": 1024, + "type": "keyword" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "drive_letter": { + "ignore_above": 1, + "type": "keyword" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fork_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "macho": { + "properties": { + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "symhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "host": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "boot": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "cpu": { + "properties": { + "usage": { + "scaling_factor": 1000, + "type": "scaled_float" + } + } + }, + "disk": { + "properties": { + "read": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "write": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "network": { + "properties": { + "egress": { + "properties": { + "bytes": { + "type": "long" + }, + "packets": { + "type": "long" + } + } + }, + "ingress": { + "properties": { + "bytes": { + "type": "long" + }, + "packets": { + "type": "long" + } + } + } + } + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pid_ns_ino": { + "ignore_above": 1024, + "type": "keyword" + }, + "risk": { + "properties": { + "calculated_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "calculated_score": { + "type": "float" + }, + "calculated_score_norm": { + "type": "float" + }, + "static_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "static_score": { + "type": "float" + }, + "static_score_norm": { + "type": "float" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uptime": { + "type": "long" + } + } + }, + "http": { + "properties": { + "request": { + "properties": { + "body": { + "properties": { + "bytes": { + "type": "long" + }, + "content": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + } + } + }, + "bytes": { + "type": "long" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "method": { + "ignore_above": 1024, + "type": "keyword" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "referrer": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "response": { + "properties": { + "body": { + "properties": { + "bytes": { + "type": "long" + }, + "content": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + } + } + }, + "bytes": { + "type": "long" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "status_code": { + "type": "long" + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "kibana": { + "properties": { + "alert": { + "properties": { + "action_group": { + "type": "keyword" + }, + "case_ids": { + "type": "keyword" + }, + "consecutive_matches": { + "type": "long" + }, + "context": { + "type": "object" + }, + "duration": { + "properties": { + "us": { + "type": "long" + } + } + }, + "end": { + "type": "date" + }, + "evaluation": { + "properties": { + "threshold": { + "scaling_factor": 100, + "type": "scaled_float" + }, + "value": { + "scaling_factor": 100, + "type": "scaled_float" + }, + "values": { + "scaling_factor": 100, + "type": "scaled_float" + } + } + }, + "flapping": { + "type": "boolean" + }, + "flapping_history": { + "type": "boolean" + }, + "group": { + "properties": { + "field": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + }, + "instance": { + "properties": { + "id": { + "type": "keyword" + } + } + }, + "intended_timestamp": { + "type": "date" + }, + "last_detected": { + "type": "date" + }, + "maintenance_window_ids": { + "type": "keyword" + }, + "previous_action_group": { + "type": "keyword" + }, + "reason": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "keyword" + }, + "risk_score": { + "type": "float" + }, + "rule": { + "properties": { + "author": { + "type": "keyword" + }, + "category": { + "type": "keyword" + }, + "consumer": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "type": "keyword" + }, + "description": { + "type": "keyword" + }, + "enabled": { + "type": "keyword" + }, + "execution": { + "properties": { + "timestamp": { + "type": "date" + }, + "type": { + "type": "keyword" + }, + "uuid": { + "type": "keyword" + } + } + }, + "from": { + "type": "keyword" + }, + "interval": { + "type": "keyword" + }, + "license": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "note": { + "type": "keyword" + }, + "parameters": { + "ignore_above": 4096, + "type": "flattened" + }, + "producer": { + "type": "keyword" + }, + "references": { + "type": "keyword" + }, + "revision": { + "type": "long" + }, + "rule_id": { + "type": "keyword" + }, + "rule_name_override": { + "type": "keyword" + }, + "rule_type_id": { + "type": "keyword" + }, + "tags": { + "type": "keyword" + }, + "to": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "type": "keyword" + }, + "uuid": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + } + }, + "severity": { + "type": "keyword" + }, + "severity_improving": { + "type": "boolean" + }, + "start": { + "type": "date" + }, + "status": { + "type": "keyword" + }, + "suppression": { + "properties": { + "docs_count": { + "type": "long" + }, + "end": { + "type": "date" + }, + "start": { + "type": "date" + }, + "terms": { + "properties": { + "field": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + } + } + }, + "system_status": { + "type": "keyword" + }, + "time_range": { + "format": "epoch_millis||strict_date_optional_time", + "type": "date_range" + }, + "url": { + "ignore_above": 2048, + "index": false, + "type": "keyword" + }, + "uuid": { + "type": "keyword" + }, + "workflow_assignee_ids": { + "type": "keyword" + }, + "workflow_reason": { + "type": "keyword" + }, + "workflow_status": { + "type": "keyword" + }, + "workflow_status_updated_at": { + "type": "date" + }, + "workflow_tags": { + "type": "keyword" + }, + "workflow_user": { + "type": "keyword" + } + } + }, + "space_ids": { + "type": "keyword" + }, + "version": { + "type": "version" + } + } + }, + "labels": { + "type": "object" + }, + "log": { + "properties": { + "file": { + "properties": { + "path": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "level": { + "ignore_above": 1024, + "type": "keyword" + }, + "logger": { + "ignore_above": 1024, + "type": "keyword" + }, + "origin": { + "properties": { + "file": { + "properties": { + "line": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "function": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "syslog": { + "properties": { + "appname": { + "ignore_above": 1024, + "type": "keyword" + }, + "facility": { + "properties": { + "code": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "msgid": { + "ignore_above": 1024, + "type": "keyword" + }, + "priority": { + "type": "long" + }, + "procid": { + "ignore_above": 1024, + "type": "keyword" + }, + "severity": { + "properties": { + "code": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "structured_data": { + "type": "flattened" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "message": { + "type": "match_only_text" + }, + "network": { + "properties": { + "application": { + "ignore_above": 1024, + "type": "keyword" + }, + "bytes": { + "type": "long" + }, + "community_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "direction": { + "ignore_above": 1024, + "type": "keyword" + }, + "forwarded_ip": { + "type": "ip" + }, + "iana_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "inner": { + "properties": { + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "packets": { + "type": "long" + }, + "protocol": { + "ignore_above": 1024, + "type": "keyword" + }, + "transport": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "observer": { + "properties": { + "egress": { + "properties": { + "interface": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "zone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "ingress": { + "properties": { + "interface": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "zone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "vendor": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "orchestrator": { + "properties": { + "api_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "cluster": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "namespace": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "resource": { + "properties": { + "annotation": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "label": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "organization": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "package": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "build_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "checksum": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "install_scope": { + "ignore_above": 1024, + "type": "keyword" + }, + "installed": { + "type": "date" + }, + "license": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "process": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "end": { + "type": "date" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "entry_leader": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "attested_groups": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "attested_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "entry_meta": { + "properties": { + "source": { + "properties": { + "ip": { + "type": "ip" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "session_leader": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "same_as_process": { + "type": "boolean" + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "env_vars": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "group_leader": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "same_as_process": { + "type": "boolean" + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "io": { + "properties": { + "bytes_skipped": { + "properties": { + "length": { + "type": "long" + }, + "offset": { + "type": "long" + } + } + }, + "max_bytes_per_process_exceeded": { + "type": "boolean" + }, + "text": { + "type": "wildcard" + }, + "total_bytes_captured": { + "type": "long" + }, + "total_bytes_skipped": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "macho": { + "properties": { + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "symhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "end": { + "type": "date" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "group_leader": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "macho": { + "properties": { + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "symhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "thread": { + "properties": { + "capabilities": { + "properties": { + "effective": { + "ignore_above": 1024, + "type": "keyword" + }, + "permitted": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "title": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "uptime": { + "type": "long" + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "previous": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "session_leader": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "session_leader": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "same_as_process": { + "type": "boolean" + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "thread": { + "properties": { + "capabilities": { + "properties": { + "effective": { + "ignore_above": 1024, + "type": "keyword" + }, + "permitted": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "title": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + }, + "columns": { + "type": "long" + }, + "rows": { + "type": "long" + } + } + }, + "uptime": { + "type": "long" + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "strings": { + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hive": { + "ignore_above": 1024, + "type": "keyword" + }, + "key": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "value": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "related": { + "properties": { + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "hosts": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "user": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "rule": { + "properties": { + "author": { + "ignore_above": 1024, + "type": "keyword" + }, + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "license": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "ruleset": { + "ignore_above": 1024, + "type": "keyword" + }, + "uuid": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "server": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "service": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "environment": { + "ignore_above": 1024, + "type": "keyword" + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "node": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "role": { + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "origin": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "environment": { + "ignore_above": 1024, + "type": "keyword" + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "node": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "role": { + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "state": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "state": { + "ignore_above": 1024, + "type": "keyword" + }, + "target": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "environment": { + "ignore_above": 1024, + "type": "keyword" + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "node": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "role": { + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "state": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "source": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "span": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tags": { + "type": "keyword" + }, + "threat": { + "properties": { + "enrichments": { + "properties": { + "indicator": { + "properties": { + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "confidence": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "ignore_above": 1024, + "type": "keyword" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "drive_letter": { + "ignore_above": 1, + "type": "keyword" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fork_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "first_seen": { + "type": "date" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "last_seen": { + "type": "date" + }, + "marking": { + "properties": { + "tlp": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlp_version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "modified_at": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "port": { + "type": "long" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "strings": { + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hive": { + "ignore_above": 1024, + "type": "keyword" + }, + "key": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "value": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "scanner_stats": { + "type": "long" + }, + "sightings": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fragment": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "password": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "type": "wildcard" + }, + "port": { + "type": "long" + }, + "query": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "scheme": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "username": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "matched": { + "properties": { + "atomic": { + "ignore_above": 1024, + "type": "keyword" + }, + "field": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "index": { + "ignore_above": 1024, + "type": "keyword" + }, + "occurred": { + "type": "date" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + }, + "type": "nested" + }, + "feed": { + "properties": { + "dashboard_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "framework": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "indicator": { + "properties": { + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "confidence": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "ignore_above": 1024, + "type": "keyword" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "drive_letter": { + "ignore_above": 1, + "type": "keyword" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fork_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "first_seen": { + "type": "date" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "last_seen": { + "type": "date" + }, + "marking": { + "properties": { + "tlp": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlp_version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "modified_at": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "port": { + "type": "long" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "strings": { + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hive": { + "ignore_above": 1024, + "type": "keyword" + }, + "key": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "value": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "scanner_stats": { + "type": "long" + }, + "sightings": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fragment": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "password": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "type": "wildcard" + }, + "port": { + "type": "long" + }, + "query": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "scheme": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "username": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "software": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "platforms": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tactic": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "technique": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "subtechnique": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "tls": { + "properties": { + "cipher": { + "ignore_above": 1024, + "type": "keyword" + }, + "client": { + "properties": { + "certificate": { + "ignore_above": 1024, + "type": "keyword" + }, + "certificate_chain": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "issuer": { + "ignore_above": 1024, + "type": "keyword" + }, + "ja3": { + "ignore_above": 1024, + "type": "keyword" + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "server_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "ignore_above": 1024, + "type": "keyword" + }, + "supported_ciphers": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "established": { + "type": "boolean" + }, + "next_protocol": { + "ignore_above": 1024, + "type": "keyword" + }, + "resumed": { + "type": "boolean" + }, + "server": { + "properties": { + "certificate": { + "ignore_above": 1024, + "type": "keyword" + }, + "certificate_chain": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "issuer": { + "ignore_above": 1024, + "type": "keyword" + }, + "ja3s": { + "ignore_above": 1024, + "type": "keyword" + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "subject": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + }, + "version_protocol": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "trace": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "transaction": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "url": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fragment": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "password": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "type": "wildcard" + }, + "port": { + "type": "long" + }, + "query": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "scheme": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "username": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "user": { + "properties": { + "changes": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "effective": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "risk": { + "properties": { + "calculated_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "calculated_score": { + "type": "float" + }, + "calculated_score_norm": { + "type": "float" + }, + "static_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "static_score": { + "type": "float" + }, + "static_score_norm": { + "type": "float" + } + } + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + }, + "target": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "user_agent": { + "properties": { + "device": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vulnerability": { + "properties": { + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "classification": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "enumeration": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "report_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "scanner": { + "properties": { + "vendor": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "score": { + "properties": { + "base": { + "type": "float" + }, + "environmental": { + "type": "float" + }, + "temporal": { + "type": "float" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "severity": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "settings": { + "index": { + "auto_expand_replicas": "0-1", + "hidden": "true", + "lifecycle": { + "name": ".alerts-ilm-policy", + "rollover_alias": ".alerts-observability.metrics.alerts-default" + }, + "mapping": { + "ignore_malformed": "true", + "total_fields": { + "limit": "2500" + } + }, + "number_of_replicas": "1", + "number_of_shards": "1" + } + } + } +} + +{ + "type": "index", + "value": { + "aliases": { + ".alerts-observability.slo.alerts-default": { + "is_write_index": true + } + }, + "index": ".internal.alerts-observability.slo.alerts-default-000001", + "mappings": { + "_meta": { + "kibana": { + "version": "9.0.0" + }, + "managed": true, + "namespace": "default" + }, + "dynamic": "false", + "properties": { + "@timestamp": { + "ignore_malformed": false, + "type": "date" + }, + "agent": { + "properties": { + "build": { + "properties": { + "original": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "client": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "cloud": { + "properties": { + "account": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "instance": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "machine": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "origin": { + "properties": { + "account": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "instance": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "machine": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "project": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "region": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "project": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "region": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "target": { + "properties": { + "account": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "instance": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "machine": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "project": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "region": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "container": { + "properties": { + "cpu": { + "properties": { + "usage": { + "scaling_factor": 1000, + "type": "scaled_float" + } + } + }, + "disk": { + "properties": { + "read": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "write": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "image": { + "properties": { + "hash": { + "properties": { + "all": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "tag": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "labels": { + "type": "object" + }, + "memory": { + "properties": { + "usage": { + "scaling_factor": 1000, + "type": "scaled_float" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "network": { + "properties": { + "egress": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "ingress": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "runtime": { + "ignore_above": 1024, + "type": "keyword" + }, + "security_context": { + "properties": { + "privileged": { + "type": "boolean" + } + } + } + } + }, + "destination": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "device": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "manufacturer": { + "ignore_above": 1024, + "type": "keyword" + }, + "model": { + "properties": { + "identifier": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "dll": { + "properties": { + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + } + } + }, + "dns": { + "properties": { + "answers": { + "properties": { + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "ttl": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "header_flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "op_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "question": { + "properties": { + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "resolved_ip": { + "type": "ip" + }, + "response_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ecs": { + "properties": { + "version": { + "type": "keyword" + } + } + }, + "email": { + "properties": { + "attachments": { + "properties": { + "file": { + "properties": { + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "size": { + "type": "long" + } + } + } + }, + "type": "nested" + }, + "bcc": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "cc": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "content_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "delivery_timestamp": { + "type": "date" + }, + "direction": { + "ignore_above": 1024, + "type": "keyword" + }, + "from": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "local_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "message_id": { + "type": "wildcard" + }, + "origination_timestamp": { + "type": "date" + }, + "reply_to": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "sender": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "subject": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "to": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "x_mailer": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "error": { + "properties": { + "code": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "message": { + "type": "match_only_text" + }, + "stack_trace": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "event": { + "properties": { + "action": { + "ignore_above": 1024, + "type": "keyword" + }, + "agent_id_status": { + "ignore_above": 1024, + "type": "keyword" + }, + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "code": { + "ignore_above": 1024, + "type": "keyword" + }, + "created": { + "type": "date" + }, + "dataset": { + "ignore_above": 1024, + "type": "keyword" + }, + "duration": { + "type": "long" + }, + "end": { + "type": "date" + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ingested": { + "type": "date" + }, + "kind": { + "ignore_above": 1024, + "type": "keyword" + }, + "module": { + "ignore_above": 1024, + "type": "keyword" + }, + "original": { + "ignore_above": 1024, + "type": "keyword" + }, + "outcome": { + "ignore_above": 1024, + "type": "keyword" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "reason": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "risk_score": { + "type": "float" + }, + "risk_score_norm": { + "type": "float" + }, + "sequence": { + "type": "long" + }, + "severity": { + "type": "long" + }, + "start": { + "type": "date" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "faas": { + "properties": { + "coldstart": { + "type": "boolean" + }, + "execution": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "ignore_above": 1024, + "type": "keyword" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "drive_letter": { + "ignore_above": 1, + "type": "keyword" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fork_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "macho": { + "properties": { + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "symhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "host": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "boot": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "cpu": { + "properties": { + "usage": { + "scaling_factor": 1000, + "type": "scaled_float" + } + } + }, + "disk": { + "properties": { + "read": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "write": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "network": { + "properties": { + "egress": { + "properties": { + "bytes": { + "type": "long" + }, + "packets": { + "type": "long" + } + } + }, + "ingress": { + "properties": { + "bytes": { + "type": "long" + }, + "packets": { + "type": "long" + } + } + } + } + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pid_ns_ino": { + "ignore_above": 1024, + "type": "keyword" + }, + "risk": { + "properties": { + "calculated_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "calculated_score": { + "type": "float" + }, + "calculated_score_norm": { + "type": "float" + }, + "static_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "static_score": { + "type": "float" + }, + "static_score_norm": { + "type": "float" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uptime": { + "type": "long" + } + } + }, + "http": { + "properties": { + "request": { + "properties": { + "body": { + "properties": { + "bytes": { + "type": "long" + }, + "content": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + } + } + }, + "bytes": { + "type": "long" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "method": { + "ignore_above": 1024, + "type": "keyword" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "referrer": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "response": { + "properties": { + "body": { + "properties": { + "bytes": { + "type": "long" + }, + "content": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + } + } + }, + "bytes": { + "type": "long" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "status_code": { + "type": "long" + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "kibana": { + "properties": { + "alert": { + "properties": { + "action_group": { + "type": "keyword" + }, + "case_ids": { + "type": "keyword" + }, + "consecutive_matches": { + "type": "long" + }, + "context": { + "type": "object" + }, + "duration": { + "properties": { + "us": { + "type": "long" + } + } + }, + "end": { + "type": "date" + }, + "evaluation": { + "properties": { + "threshold": { + "scaling_factor": 100, + "type": "scaled_float" + }, + "value": { + "scaling_factor": 100, + "type": "scaled_float" + }, + "values": { + "scaling_factor": 100, + "type": "scaled_float" + } + } + }, + "flapping": { + "type": "boolean" + }, + "flapping_history": { + "type": "boolean" + }, + "group": { + "properties": { + "field": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + }, + "instance": { + "properties": { + "id": { + "type": "keyword" + } + } + }, + "intended_timestamp": { + "type": "date" + }, + "last_detected": { + "type": "date" + }, + "maintenance_window_ids": { + "type": "keyword" + }, + "previous_action_group": { + "type": "keyword" + }, + "reason": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "keyword" + }, + "risk_score": { + "type": "float" + }, + "rule": { + "properties": { + "author": { + "type": "keyword" + }, + "category": { + "type": "keyword" + }, + "consumer": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "type": "keyword" + }, + "description": { + "type": "keyword" + }, + "enabled": { + "type": "keyword" + }, + "execution": { + "properties": { + "timestamp": { + "type": "date" + }, + "type": { + "type": "keyword" + }, + "uuid": { + "type": "keyword" + } + } + }, + "from": { + "type": "keyword" + }, + "interval": { + "type": "keyword" + }, + "license": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "note": { + "type": "keyword" + }, + "parameters": { + "ignore_above": 4096, + "type": "flattened" + }, + "producer": { + "type": "keyword" + }, + "references": { + "type": "keyword" + }, + "revision": { + "type": "long" + }, + "rule_id": { + "type": "keyword" + }, + "rule_name_override": { + "type": "keyword" + }, + "rule_type_id": { + "type": "keyword" + }, + "tags": { + "type": "keyword" + }, + "to": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "type": "keyword" + }, + "uuid": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + } + }, + "severity": { + "type": "keyword" + }, + "severity_improving": { + "type": "boolean" + }, + "start": { + "type": "date" + }, + "status": { + "type": "keyword" + }, + "suppression": { + "properties": { + "docs_count": { + "type": "long" + }, + "end": { + "type": "date" + }, + "start": { + "type": "date" + }, + "terms": { + "properties": { + "field": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + } + } + }, + "system_status": { + "type": "keyword" + }, + "time_range": { + "format": "epoch_millis||strict_date_optional_time", + "type": "date_range" + }, + "url": { + "ignore_above": 2048, + "index": false, + "type": "keyword" + }, + "uuid": { + "type": "keyword" + }, + "workflow_assignee_ids": { + "type": "keyword" + }, + "workflow_reason": { + "type": "keyword" + }, + "workflow_status": { + "type": "keyword" + }, + "workflow_status_updated_at": { + "type": "date" + }, + "workflow_tags": { + "type": "keyword" + }, + "workflow_user": { + "type": "keyword" + } + } + }, + "space_ids": { + "type": "keyword" + }, + "version": { + "type": "version" + } + } + }, + "labels": { + "type": "object" + }, + "log": { + "properties": { + "file": { + "properties": { + "path": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "level": { + "ignore_above": 1024, + "type": "keyword" + }, + "logger": { + "ignore_above": 1024, + "type": "keyword" + }, + "origin": { + "properties": { + "file": { + "properties": { + "line": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "function": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "syslog": { + "properties": { + "appname": { + "ignore_above": 1024, + "type": "keyword" + }, + "facility": { + "properties": { + "code": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "msgid": { + "ignore_above": 1024, + "type": "keyword" + }, + "priority": { + "type": "long" + }, + "procid": { + "ignore_above": 1024, + "type": "keyword" + }, + "severity": { + "properties": { + "code": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "structured_data": { + "type": "flattened" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "message": { + "type": "match_only_text" + }, + "network": { + "properties": { + "application": { + "ignore_above": 1024, + "type": "keyword" + }, + "bytes": { + "type": "long" + }, + "community_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "direction": { + "ignore_above": 1024, + "type": "keyword" + }, + "forwarded_ip": { + "type": "ip" + }, + "iana_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "inner": { + "properties": { + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "packets": { + "type": "long" + }, + "protocol": { + "ignore_above": 1024, + "type": "keyword" + }, + "transport": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "observer": { + "properties": { + "egress": { + "properties": { + "interface": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "zone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "ingress": { + "properties": { + "interface": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "zone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "vendor": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "orchestrator": { + "properties": { + "api_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "cluster": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "namespace": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "resource": { + "properties": { + "annotation": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "label": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "organization": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "package": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "build_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "checksum": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "install_scope": { + "ignore_above": 1024, + "type": "keyword" + }, + "installed": { + "type": "date" + }, + "license": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "process": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "end": { + "type": "date" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "entry_leader": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "attested_groups": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "attested_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "entry_meta": { + "properties": { + "source": { + "properties": { + "ip": { + "type": "ip" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "session_leader": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "same_as_process": { + "type": "boolean" + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "env_vars": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "group_leader": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "same_as_process": { + "type": "boolean" + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "io": { + "properties": { + "bytes_skipped": { + "properties": { + "length": { + "type": "long" + }, + "offset": { + "type": "long" + } + } + }, + "max_bytes_per_process_exceeded": { + "type": "boolean" + }, + "text": { + "type": "wildcard" + }, + "total_bytes_captured": { + "type": "long" + }, + "total_bytes_skipped": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "macho": { + "properties": { + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "symhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "end": { + "type": "date" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "group_leader": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "macho": { + "properties": { + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "symhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "thread": { + "properties": { + "capabilities": { + "properties": { + "effective": { + "ignore_above": 1024, + "type": "keyword" + }, + "permitted": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "title": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "uptime": { + "type": "long" + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "previous": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "session_leader": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "session_leader": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "same_as_process": { + "type": "boolean" + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "thread": { + "properties": { + "capabilities": { + "properties": { + "effective": { + "ignore_above": 1024, + "type": "keyword" + }, + "permitted": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "title": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + }, + "columns": { + "type": "long" + }, + "rows": { + "type": "long" + } + } + }, + "uptime": { + "type": "long" + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "strings": { + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hive": { + "ignore_above": 1024, + "type": "keyword" + }, + "key": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "value": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "related": { + "properties": { + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "hosts": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "user": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "rule": { + "properties": { + "author": { + "ignore_above": 1024, + "type": "keyword" + }, + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "license": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "ruleset": { + "ignore_above": 1024, + "type": "keyword" + }, + "uuid": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "server": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "service": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "environment": { + "ignore_above": 1024, + "type": "keyword" + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "node": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "role": { + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "origin": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "environment": { + "ignore_above": 1024, + "type": "keyword" + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "node": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "role": { + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "state": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "state": { + "ignore_above": 1024, + "type": "keyword" + }, + "target": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "environment": { + "ignore_above": 1024, + "type": "keyword" + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "node": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "role": { + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "state": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "slo": { + "properties": { + "id": { + "type": "keyword" + }, + "instanceId": { + "type": "keyword" + }, + "revision": { + "type": "long" + } + } + }, + "source": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "span": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tags": { + "type": "keyword" + }, + "threat": { + "properties": { + "enrichments": { + "properties": { + "indicator": { + "properties": { + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "confidence": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "ignore_above": 1024, + "type": "keyword" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "drive_letter": { + "ignore_above": 1, + "type": "keyword" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fork_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "first_seen": { + "type": "date" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "last_seen": { + "type": "date" + }, + "marking": { + "properties": { + "tlp": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlp_version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "modified_at": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "port": { + "type": "long" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "strings": { + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hive": { + "ignore_above": 1024, + "type": "keyword" + }, + "key": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "value": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "scanner_stats": { + "type": "long" + }, + "sightings": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fragment": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "password": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "type": "wildcard" + }, + "port": { + "type": "long" + }, + "query": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "scheme": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "username": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "matched": { + "properties": { + "atomic": { + "ignore_above": 1024, + "type": "keyword" + }, + "field": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "index": { + "ignore_above": 1024, + "type": "keyword" + }, + "occurred": { + "type": "date" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + }, + "type": "nested" + }, + "feed": { + "properties": { + "dashboard_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "framework": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "indicator": { + "properties": { + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "confidence": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "ignore_above": 1024, + "type": "keyword" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "drive_letter": { + "ignore_above": 1, + "type": "keyword" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fork_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "first_seen": { + "type": "date" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "last_seen": { + "type": "date" + }, + "marking": { + "properties": { + "tlp": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlp_version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "modified_at": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "port": { + "type": "long" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "strings": { + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hive": { + "ignore_above": 1024, + "type": "keyword" + }, + "key": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "value": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "scanner_stats": { + "type": "long" + }, + "sightings": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fragment": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "password": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "type": "wildcard" + }, + "port": { + "type": "long" + }, + "query": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "scheme": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "username": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "software": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "platforms": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tactic": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "technique": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "subtechnique": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "tls": { + "properties": { + "cipher": { + "ignore_above": 1024, + "type": "keyword" + }, + "client": { + "properties": { + "certificate": { + "ignore_above": 1024, + "type": "keyword" + }, + "certificate_chain": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "issuer": { + "ignore_above": 1024, + "type": "keyword" + }, + "ja3": { + "ignore_above": 1024, + "type": "keyword" + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "server_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "ignore_above": 1024, + "type": "keyword" + }, + "supported_ciphers": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "established": { + "type": "boolean" + }, + "next_protocol": { + "ignore_above": 1024, + "type": "keyword" + }, + "resumed": { + "type": "boolean" + }, + "server": { + "properties": { + "certificate": { + "ignore_above": 1024, + "type": "keyword" + }, + "certificate_chain": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "issuer": { + "ignore_above": 1024, + "type": "keyword" + }, + "ja3s": { + "ignore_above": 1024, + "type": "keyword" + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "subject": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + }, + "version_protocol": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "trace": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "transaction": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "url": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fragment": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "password": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "type": "wildcard" + }, + "port": { + "type": "long" + }, + "query": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "scheme": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "username": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "user": { + "properties": { + "changes": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "effective": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "risk": { + "properties": { + "calculated_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "calculated_score": { + "type": "float" + }, + "calculated_score_norm": { + "type": "float" + }, + "static_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "static_score": { + "type": "float" + }, + "static_score_norm": { + "type": "float" + } + } + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + }, + "target": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "user_agent": { + "properties": { + "device": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vulnerability": { + "properties": { + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "classification": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "enumeration": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "report_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "scanner": { + "properties": { + "vendor": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "score": { + "properties": { + "base": { + "type": "float" + }, + "environmental": { + "type": "float" + }, + "temporal": { + "type": "float" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "severity": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "settings": { + "index": { + "auto_expand_replicas": "0-1", + "hidden": "true", + "lifecycle": { + "name": ".alerts-ilm-policy", + "rollover_alias": ".alerts-observability.slo.alerts-default" + }, + "mapping": { + "ignore_malformed": "true", + "total_fields": { + "limit": "2500" + } + }, + "number_of_replicas": "1", + "number_of_shards": "1" + } + } + } +} + +{ + "type": "index", + "value": { + "aliases": { + ".alerts-observability.threshold.alerts-default": { + "is_write_index": true + } + }, + "index": ".internal.alerts-observability.threshold.alerts-default-000001", + "mappings": { + "_meta": { + "kibana": { + "version": "9.0.0" + }, + "managed": true, + "namespace": "default" + }, + "dynamic": "false", + "properties": { + "@timestamp": { + "ignore_malformed": false, + "type": "date" + }, + "agent": { + "properties": { + "build": { + "properties": { + "original": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "client": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "cloud": { + "properties": { + "account": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "instance": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "machine": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "origin": { + "properties": { + "account": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "instance": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "machine": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "project": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "region": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "project": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "region": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "target": { + "properties": { + "account": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "instance": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "machine": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "project": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "region": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "container": { + "properties": { + "cpu": { + "properties": { + "usage": { + "scaling_factor": 1000, + "type": "scaled_float" + } + } + }, + "disk": { + "properties": { + "read": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "write": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "image": { + "properties": { + "hash": { + "properties": { + "all": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "tag": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "labels": { + "type": "object" + }, + "memory": { + "properties": { + "usage": { + "scaling_factor": 1000, + "type": "scaled_float" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "network": { + "properties": { + "egress": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "ingress": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "runtime": { + "ignore_above": 1024, + "type": "keyword" + }, + "security_context": { + "properties": { + "privileged": { + "type": "boolean" + } + } + } + } + }, + "destination": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "device": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "manufacturer": { + "ignore_above": 1024, + "type": "keyword" + }, + "model": { + "properties": { + "identifier": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "dll": { + "properties": { + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + } + } + }, + "dns": { + "properties": { + "answers": { + "properties": { + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "ttl": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "header_flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "op_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "question": { + "properties": { + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "resolved_ip": { + "type": "ip" + }, + "response_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ecs": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "email": { + "properties": { + "attachments": { + "properties": { + "file": { + "properties": { + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "size": { + "type": "long" + } + } + } + }, + "type": "nested" + }, + "bcc": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "cc": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "content_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "delivery_timestamp": { + "type": "date" + }, + "direction": { + "ignore_above": 1024, + "type": "keyword" + }, + "from": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "local_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "message_id": { + "type": "wildcard" + }, + "origination_timestamp": { + "type": "date" + }, + "reply_to": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "sender": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "subject": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "to": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "x_mailer": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "error": { + "properties": { + "code": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "message": { + "type": "match_only_text" + }, + "stack_trace": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "event": { + "properties": { + "action": { + "ignore_above": 1024, + "type": "keyword" + }, + "agent_id_status": { + "ignore_above": 1024, + "type": "keyword" + }, + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "code": { + "ignore_above": 1024, + "type": "keyword" + }, + "created": { + "type": "date" + }, + "dataset": { + "ignore_above": 1024, + "type": "keyword" + }, + "duration": { + "type": "long" + }, + "end": { + "type": "date" + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ingested": { + "type": "date" + }, + "kind": { + "ignore_above": 1024, + "type": "keyword" + }, + "module": { + "ignore_above": 1024, + "type": "keyword" + }, + "original": { + "ignore_above": 1024, + "type": "keyword" + }, + "outcome": { + "ignore_above": 1024, + "type": "keyword" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "reason": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "risk_score": { + "type": "float" + }, + "risk_score_norm": { + "type": "float" + }, + "sequence": { + "type": "long" + }, + "severity": { + "type": "long" + }, + "start": { + "type": "date" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "faas": { + "properties": { + "coldstart": { + "type": "boolean" + }, + "execution": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "ignore_above": 1024, + "type": "keyword" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "drive_letter": { + "ignore_above": 1, + "type": "keyword" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fork_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "macho": { + "properties": { + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "symhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "host": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "boot": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "cpu": { + "properties": { + "usage": { + "scaling_factor": 1000, + "type": "scaled_float" + } + } + }, + "disk": { + "properties": { + "read": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "write": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "network": { + "properties": { + "egress": { + "properties": { + "bytes": { + "type": "long" + }, + "packets": { + "type": "long" + } + } + }, + "ingress": { + "properties": { + "bytes": { + "type": "long" + }, + "packets": { + "type": "long" + } + } + } + } + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pid_ns_ino": { + "ignore_above": 1024, + "type": "keyword" + }, + "risk": { + "properties": { + "calculated_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "calculated_score": { + "type": "float" + }, + "calculated_score_norm": { + "type": "float" + }, + "static_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "static_score": { + "type": "float" + }, + "static_score_norm": { + "type": "float" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uptime": { + "type": "long" + } + } + }, + "http": { + "properties": { + "request": { + "properties": { + "body": { + "properties": { + "bytes": { + "type": "long" + }, + "content": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + } + } + }, + "bytes": { + "type": "long" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "method": { + "ignore_above": 1024, + "type": "keyword" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "referrer": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "response": { + "properties": { + "body": { + "properties": { + "bytes": { + "type": "long" + }, + "content": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + } + } + }, + "bytes": { + "type": "long" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "status_code": { + "type": "long" + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "kibana": { + "properties": { + "alert": { + "properties": { + "action_group": { + "type": "keyword" + }, + "case_ids": { + "type": "keyword" + }, + "consecutive_matches": { + "type": "long" + }, + "context": { + "type": "object" + }, + "duration": { + "properties": { + "us": { + "type": "long" + } + } + }, + "end": { + "type": "date" + }, + "evaluation": { + "properties": { + "threshold": { + "scaling_factor": 100, + "type": "scaled_float" + }, + "value": { + "scaling_factor": 100, + "type": "scaled_float" + }, + "values": { + "scaling_factor": 100, + "type": "scaled_float" + } + } + }, + "flapping": { + "type": "boolean" + }, + "flapping_history": { + "type": "boolean" + }, + "group": { + "properties": { + "field": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + }, + "instance": { + "properties": { + "id": { + "type": "keyword" + } + } + }, + "intended_timestamp": { + "type": "date" + }, + "last_detected": { + "type": "date" + }, + "maintenance_window_ids": { + "type": "keyword" + }, + "previous_action_group": { + "type": "keyword" + }, + "reason": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "keyword" + }, + "rule": { + "properties": { + "category": { + "type": "keyword" + }, + "consumer": { + "type": "keyword" + }, + "execution": { + "properties": { + "timestamp": { + "type": "date" + }, + "type": { + "type": "keyword" + }, + "uuid": { + "type": "keyword" + } + } + }, + "name": { + "type": "keyword" + }, + "parameters": { + "ignore_above": 4096, + "type": "flattened" + }, + "producer": { + "type": "keyword" + }, + "revision": { + "type": "long" + }, + "rule_type_id": { + "type": "keyword" + }, + "tags": { + "type": "keyword" + }, + "uuid": { + "type": "keyword" + } + } + }, + "severity_improving": { + "type": "boolean" + }, + "start": { + "type": "date" + }, + "status": { + "type": "keyword" + }, + "time_range": { + "format": "epoch_millis||strict_date_optional_time", + "type": "date_range" + }, + "url": { + "ignore_above": 2048, + "index": false, + "type": "keyword" + }, + "uuid": { + "type": "keyword" + }, + "workflow_assignee_ids": { + "type": "keyword" + }, + "workflow_status": { + "type": "keyword" + }, + "workflow_tags": { + "type": "keyword" + } + } + }, + "space_ids": { + "type": "keyword" + }, + "version": { + "type": "version" + } + } + }, + "labels": { + "type": "object" + }, + "log": { + "properties": { + "file": { + "properties": { + "path": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "level": { + "ignore_above": 1024, + "type": "keyword" + }, + "logger": { + "ignore_above": 1024, + "type": "keyword" + }, + "origin": { + "properties": { + "file": { + "properties": { + "line": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "function": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "syslog": { + "properties": { + "appname": { + "ignore_above": 1024, + "type": "keyword" + }, + "facility": { + "properties": { + "code": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "msgid": { + "ignore_above": 1024, + "type": "keyword" + }, + "priority": { + "type": "long" + }, + "procid": { + "ignore_above": 1024, + "type": "keyword" + }, + "severity": { + "properties": { + "code": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "structured_data": { + "type": "flattened" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "message": { + "type": "match_only_text" + }, + "network": { + "properties": { + "application": { + "ignore_above": 1024, + "type": "keyword" + }, + "bytes": { + "type": "long" + }, + "community_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "direction": { + "ignore_above": 1024, + "type": "keyword" + }, + "forwarded_ip": { + "type": "ip" + }, + "iana_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "inner": { + "properties": { + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "packets": { + "type": "long" + }, + "protocol": { + "ignore_above": 1024, + "type": "keyword" + }, + "transport": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "observer": { + "properties": { + "egress": { + "properties": { + "interface": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "zone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "ingress": { + "properties": { + "interface": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "zone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "vendor": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "orchestrator": { + "properties": { + "api_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "cluster": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "namespace": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "resource": { + "properties": { + "annotation": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "label": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "organization": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "package": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "build_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "checksum": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "install_scope": { + "ignore_above": 1024, + "type": "keyword" + }, + "installed": { + "type": "date" + }, + "license": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "process": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "end": { + "type": "date" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "entry_leader": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "attested_groups": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "attested_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "entry_meta": { + "properties": { + "source": { + "properties": { + "ip": { + "type": "ip" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "session_leader": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "same_as_process": { + "type": "boolean" + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "env_vars": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "group_leader": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "same_as_process": { + "type": "boolean" + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "io": { + "properties": { + "bytes_skipped": { + "properties": { + "length": { + "type": "long" + }, + "offset": { + "type": "long" + } + } + }, + "max_bytes_per_process_exceeded": { + "type": "boolean" + }, + "text": { + "type": "wildcard" + }, + "total_bytes_captured": { + "type": "long" + }, + "total_bytes_skipped": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "macho": { + "properties": { + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "symhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "end": { + "type": "date" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "group_leader": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "macho": { + "properties": { + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "symhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "thread": { + "properties": { + "capabilities": { + "properties": { + "effective": { + "ignore_above": 1024, + "type": "keyword" + }, + "permitted": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "title": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "uptime": { + "type": "long" + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "previous": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "session_leader": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "session_leader": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "start": { + "type": "date" + }, + "vpid": { + "type": "long" + } + } + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "same_as_process": { + "type": "boolean" + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "thread": { + "properties": { + "capabilities": { + "properties": { + "effective": { + "ignore_above": 1024, + "type": "keyword" + }, + "permitted": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "title": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + }, + "columns": { + "type": "long" + }, + "rows": { + "type": "long" + } + } + }, + "uptime": { + "type": "long" + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vpid": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "strings": { + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hive": { + "ignore_above": 1024, + "type": "keyword" + }, + "key": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "value": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "related": { + "properties": { + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "hosts": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "user": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "rule": { + "properties": { + "author": { + "ignore_above": 1024, + "type": "keyword" + }, + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "license": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "ruleset": { + "ignore_above": 1024, + "type": "keyword" + }, + "uuid": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "server": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "service": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "environment": { + "ignore_above": 1024, + "type": "keyword" + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "node": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "role": { + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "origin": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "environment": { + "ignore_above": 1024, + "type": "keyword" + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "node": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "role": { + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "state": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "state": { + "ignore_above": 1024, + "type": "keyword" + }, + "target": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "environment": { + "ignore_above": 1024, + "type": "keyword" + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "node": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "role": { + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "state": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "source": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "span": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tags": { + "type": "keyword" + }, + "threat": { + "properties": { + "enrichments": { + "properties": { + "indicator": { + "properties": { + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "confidence": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "ignore_above": 1024, + "type": "keyword" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "drive_letter": { + "ignore_above": 1, + "type": "keyword" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fork_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "first_seen": { + "type": "date" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "last_seen": { + "type": "date" + }, + "marking": { + "properties": { + "tlp": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlp_version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "modified_at": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "port": { + "type": "long" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "strings": { + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hive": { + "ignore_above": 1024, + "type": "keyword" + }, + "key": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "value": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "scanner_stats": { + "type": "long" + }, + "sightings": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fragment": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "password": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "type": "wildcard" + }, + "port": { + "type": "long" + }, + "query": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "scheme": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "username": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "matched": { + "properties": { + "atomic": { + "ignore_above": 1024, + "type": "keyword" + }, + "field": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "index": { + "ignore_above": 1024, + "type": "keyword" + }, + "occurred": { + "type": "date" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + }, + "type": "nested" + }, + "feed": { + "properties": { + "dashboard_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "framework": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "indicator": { + "properties": { + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "confidence": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "ignore_above": 1024, + "type": "keyword" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "drive_letter": { + "ignore_above": 1, + "type": "keyword" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "var_entropy": { + "type": "long" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fork_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "go_imports": { + "type": "flattened" + }, + "go_imports_names_entropy": { + "type": "long" + }, + "go_imports_names_var_entropy": { + "type": "long" + }, + "go_stripped": { + "type": "boolean" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "import_hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "imports": { + "type": "flattened" + }, + "imports_names_entropy": { + "type": "long" + }, + "imports_names_var_entropy": { + "type": "long" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "sections": { + "properties": { + "entropy": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "var_entropy": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "first_seen": { + "type": "date" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "last_seen": { + "type": "date" + }, + "marking": { + "properties": { + "tlp": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlp_version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "modified_at": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "port": { + "type": "long" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "strings": { + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hive": { + "ignore_above": 1024, + "type": "keyword" + }, + "key": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "value": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "scanner_stats": { + "type": "long" + }, + "sightings": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fragment": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "password": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "type": "wildcard" + }, + "port": { + "type": "long" + }, + "query": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "scheme": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "username": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "software": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "platforms": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tactic": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "technique": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "subtechnique": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "tls": { + "properties": { + "cipher": { + "ignore_above": 1024, + "type": "keyword" + }, + "client": { + "properties": { + "certificate": { + "ignore_above": 1024, + "type": "keyword" + }, + "certificate_chain": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "issuer": { + "ignore_above": 1024, + "type": "keyword" + }, + "ja3": { + "ignore_above": 1024, + "type": "keyword" + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "server_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "ignore_above": 1024, + "type": "keyword" + }, + "supported_ciphers": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "established": { + "type": "boolean" + }, + "next_protocol": { + "ignore_above": 1024, + "type": "keyword" + }, + "resumed": { + "type": "boolean" + }, + "server": { + "properties": { + "certificate": { + "ignore_above": 1024, + "type": "keyword" + }, + "certificate_chain": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "issuer": { + "ignore_above": 1024, + "type": "keyword" + }, + "ja3s": { + "ignore_above": 1024, + "type": "keyword" + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "subject": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + }, + "version_protocol": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "trace": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "transaction": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "url": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fragment": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "password": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "type": "wildcard" + }, + "port": { + "type": "long" + }, + "query": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "scheme": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "username": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "user": { + "properties": { + "changes": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "effective": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "risk": { + "properties": { + "calculated_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "calculated_score": { + "type": "float" + }, + "calculated_score_norm": { + "type": "float" + }, + "static_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "static_score": { + "type": "float" + }, + "static_score_norm": { + "type": "float" + } + } + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + }, + "target": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "user_agent": { + "properties": { + "device": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vulnerability": { + "properties": { + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "classification": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "enumeration": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "report_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "scanner": { + "properties": { + "vendor": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "score": { + "properties": { + "base": { + "type": "float" + }, + "environmental": { + "type": "float" + }, + "temporal": { + "type": "float" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "severity": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "settings": { + "index": { + "auto_expand_replicas": "0-1", + "hidden": "true", + "lifecycle": { + "name": ".alerts-ilm-policy", + "rollover_alias": ".alerts-observability.threshold.alerts-default" + }, + "mapping": { + "ignore_malformed": "true", + "total_fields": { + "limit": "2500" + } + }, + "number_of_replicas": "1", + "number_of_shards": "1" + } + } + } +} + +{ + "type": "index", + "value": { + "aliases": { + ".alerts-observability.uptime.alerts-default": { + "is_write_index": true + } + }, + "index": ".internal.alerts-observability.uptime.alerts-default-000001", + "mappings": { + "_meta": { + "kibana": { + "version": "9.0.0" + }, + "managed": true, + "namespace": "default" + }, + "dynamic": "false", + "properties": { + "@timestamp": { + "ignore_malformed": false, + "type": "date" + }, + "agent": { + "properties": { + "name": { + "type": "keyword" + } + } + }, + "anomaly": { + "properties": { + "bucket_span": { + "properties": { + "minutes": { + "type": "keyword" + } + } + }, + "start": { + "type": "date" + } + } + }, + "configId": { + "type": "keyword" + }, + "ecs": { + "properties": { + "version": { + "type": "keyword" + } + } + }, + "error": { + "properties": { + "message": { + "type": "text" + }, + "stack_trace": { + "type": "wildcard" + } + } + }, + "event": { + "properties": { + "action": { + "ignore_above": 1024, + "type": "keyword" + }, + "kind": { + "ignore_above": 1024, + "type": "keyword" + }, + "original": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "host": { + "properties": { + "name": { + "type": "keyword" + } + } + }, + "kibana": { + "properties": { + "alert": { + "properties": { + "action_group": { + "type": "keyword" + }, + "case_ids": { + "type": "keyword" + }, + "consecutive_matches": { + "type": "long" + }, + "context": { + "type": "object" + }, + "duration": { + "properties": { + "us": { + "type": "long" + } + } + }, + "end": { + "type": "date" + }, + "evaluation": { + "properties": { + "threshold": { + "scaling_factor": 100, + "type": "scaled_float" + }, + "value": { + "scaling_factor": 100, + "type": "scaled_float" + }, + "values": { + "scaling_factor": 100, + "type": "scaled_float" + } + } + }, + "flapping": { + "type": "boolean" + }, + "flapping_history": { + "type": "boolean" + }, + "group": { + "properties": { + "field": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + }, + "instance": { + "properties": { + "id": { + "type": "keyword" + } + } + }, + "intended_timestamp": { + "type": "date" + }, + "last_detected": { + "type": "date" + }, + "maintenance_window_ids": { + "type": "keyword" + }, + "previous_action_group": { + "type": "keyword" + }, + "reason": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "keyword" + }, + "risk_score": { + "type": "float" + }, + "rule": { + "properties": { + "author": { + "type": "keyword" + }, + "category": { + "type": "keyword" + }, + "consumer": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "type": "keyword" + }, + "description": { + "type": "keyword" + }, + "enabled": { + "type": "keyword" + }, + "execution": { + "properties": { + "timestamp": { + "type": "date" + }, + "type": { + "type": "keyword" + }, + "uuid": { + "type": "keyword" + } + } + }, + "from": { + "type": "keyword" + }, + "interval": { + "type": "keyword" + }, + "license": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "note": { + "type": "keyword" + }, + "parameters": { + "ignore_above": 4096, + "type": "flattened" + }, + "producer": { + "type": "keyword" + }, + "references": { + "type": "keyword" + }, + "revision": { + "type": "long" + }, + "rule_id": { + "type": "keyword" + }, + "rule_name_override": { + "type": "keyword" + }, + "rule_type_id": { + "type": "keyword" + }, + "tags": { + "type": "keyword" + }, + "to": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "type": "keyword" + }, + "uuid": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + } + }, + "severity": { + "type": "keyword" + }, + "severity_improving": { + "type": "boolean" + }, + "start": { + "type": "date" + }, + "status": { + "type": "keyword" + }, + "suppression": { + "properties": { + "docs_count": { + "type": "long" + }, + "end": { + "type": "date" + }, + "start": { + "type": "date" + }, + "terms": { + "properties": { + "field": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + } + } + }, + "system_status": { + "type": "keyword" + }, + "time_range": { + "format": "epoch_millis||strict_date_optional_time", + "type": "date_range" + }, + "url": { + "ignore_above": 2048, + "index": false, + "type": "keyword" + }, + "uuid": { + "type": "keyword" + }, + "workflow_assignee_ids": { + "type": "keyword" + }, + "workflow_reason": { + "type": "keyword" + }, + "workflow_status": { + "type": "keyword" + }, + "workflow_status_updated_at": { + "type": "date" + }, + "workflow_tags": { + "type": "keyword" + }, + "workflow_user": { + "type": "keyword" + } + } + }, + "space_ids": { + "type": "keyword" + }, + "version": { + "type": "version" + } + } + }, + "labels": { + "type": "object" + }, + "location": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + } + } + }, + "monitor": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "state": { + "properties": { + "id": { + "type": "keyword" + } + } + }, + "tags": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "observer": { + "properties": { + "geo": { + "properties": { + "name": { + "type": "keyword" + } + } + }, + "name": { + "type": "keyword" + } + } + }, + "service": { + "properties": { + "name": { + "type": "keyword" + } + } + }, + "tags": { + "type": "keyword" + }, + "tls": { + "properties": { + "server": { + "properties": { + "hash": { + "properties": { + "sha256": { + "type": "keyword" + } + } + }, + "x509": { + "properties": { + "issuer": { + "properties": { + "common_name": { + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "subject": { + "properties": { + "common_name": { + "type": "keyword" + } + } + } + } + } + } + } + } + }, + "url": { + "properties": { + "full": { + "type": "keyword" + } + } + } + } + }, + "settings": { + "index": { + "auto_expand_replicas": "0-1", + "hidden": "true", + "lifecycle": { + "name": ".alerts-ilm-policy", + "rollover_alias": ".alerts-observability.uptime.alerts-default" + }, + "mapping": { + "ignore_malformed": "true", + "total_fields": { + "limit": "2500" + } + }, + "number_of_replicas": "1", + "number_of_shards": "1" + } + } + } +} \ No newline at end of file diff --git a/x-pack/solutions/observability/plugins/investigate_app/scripts/load/index.js b/x-pack/solutions/observability/plugins/investigate_app/scripts/load/index.js new file mode 100644 index 0000000000000..e4ff64980bb6e --- /dev/null +++ b/x-pack/solutions/observability/plugins/investigate_app/scripts/load/index.js @@ -0,0 +1,17 @@ +/* + * 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. + */ + +/* + * 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. + */ + +require('@kbn/babel-register').install(); + +require('./load'); diff --git a/x-pack/solutions/observability/plugins/investigate_app/scripts/load/load.ts b/x-pack/solutions/observability/plugins/investigate_app/scripts/load/load.ts new file mode 100644 index 0000000000000..e27f38c6d405e --- /dev/null +++ b/x-pack/solutions/observability/plugins/investigate_app/scripts/load/load.ts @@ -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 axios from 'axios'; +import { spawnSync } from 'child_process'; +import { run } from '@kbn/dev-cli-runner'; +import { ToolingLog } from '@kbn/tooling-log'; +import { getServiceUrls } from '@kbn/observability-ai-assistant-app-plugin/scripts/evaluation/get_service_urls'; +import yargs from 'yargs'; +import fs from 'fs'; +import path from 'path'; +import { options } from './cli'; + +async function loadFixtureData({ + esUrl, + kibanaUrl, + log, +}: { + esUrl: string; + kibanaUrl: string; + log: ToolingLog; +}) { + const directory = `${__dirname}/fixtures`; + const directories = getDirectories({ filePath: `${__dirname}/fixtures`, log }); + await axios.post( + `${kibanaUrl}/internal/kibana/settings`, + { + changes: { + 'observability:logSources': [ + 'remote_cluster:logs-*-*', + 'remote_cluster:logs-*', + 'remote_cluster:filebeat-*', + ], + }, + }, + { + headers: { + 'kbn-xsrf': 'foo', + 'x-elastic-internal-origin': 'observability-ai-assistant', + }, + } + ); + log.info('Logs sources updated'); + directories.forEach((dir) => { + spawnSync( + 'node', + [ + 'scripts/es_archiver', + 'load', + `${directory}/${dir}`, + '--es-url', + esUrl, + '--kibana-url', + kibanaUrl, + ], + { + stdio: 'inherit', + } + ); + }); +} + +function getDirectories({ filePath, log }: { filePath: string; log: ToolingLog }): string[] { + try { + const items = fs.readdirSync(filePath); + const folders = items.filter((item) => { + const itemPath = path.join(filePath, item); + return fs.statSync(itemPath).isDirectory(); + }); + return folders; + } catch (error) { + log.error(`Error reading directory: ${error.message}`); + return []; + } +} + +function loadData() { + yargs(process.argv.slice(2)) + .command('*', 'Load RCA data', async () => { + const argv = await options(yargs); + run( + async ({ log }) => { + const serviceUrls = await getServiceUrls({ + log, + elasticsearch: argv.elasticsearch, + kibana: argv.kibana, + }); + loadFixtureData({ + esUrl: serviceUrls.esUrl, + kibanaUrl: serviceUrls.kibanaUrl, + log, + }); + }, + { + log: { + defaultLevel: argv.logLevel as any, + }, + flags: { + allowUnexpected: true, + }, + } + ); + }) + .parse(); +} + +loadData(); diff --git a/x-pack/solutions/observability/plugins/investigate_app/server/services/create_investigation.ts b/x-pack/solutions/observability/plugins/investigate_app/server/services/create_investigation.ts index 6a7355c0ef875..2f1bdf51d1d5a 100644 --- a/x-pack/solutions/observability/plugins/investigate_app/server/services/create_investigation.ts +++ b/x-pack/solutions/observability/plugins/investigate_app/server/services/create_investigation.ts @@ -4,7 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import { CreateInvestigationParams, CreateInvestigationResponse } from '@kbn/investigation-shared'; import type { AuthenticatedUser } from '@kbn/core-security-common'; import { InvestigationRepository } from './investigation_repository'; @@ -23,7 +22,7 @@ export async function createInvestigation( ...params, updatedAt: now, createdAt: now, - createdBy: user.profile_uid!, + createdBy: user.profile_uid! || user.username, status: 'triage', notes: [], items: [], diff --git a/x-pack/solutions/observability/plugins/investigate_app/tsconfig.json b/x-pack/solutions/observability/plugins/investigate_app/tsconfig.json index 55e63cfdcf95f..e467bd40918fd 100644 --- a/x-pack/solutions/observability/plugins/investigate_app/tsconfig.json +++ b/x-pack/solutions/observability/plugins/investigate_app/tsconfig.json @@ -10,6 +10,7 @@ "typings/**/*", "public/**/*.json", "server/**/*", + "scripts/**/*", ".storybook/**/*" ], "exclude": [ @@ -80,5 +81,10 @@ "@kbn/utility-types-jest", "@kbn/visualization-utils", "@kbn/zod", + "@kbn/babel-register", + "@kbn/tooling-log", + "@kbn/dev-cli-runner", + "@kbn/datemath", + "@kbn/sse-utils-client", ], } diff --git a/x-pack/solutions/observability/plugins/logs_explorer/common/data_views/models/data_view_descriptor.ts b/x-pack/solutions/observability/plugins/logs_explorer/common/data_views/models/data_view_descriptor.ts index b5fe3d1f58c0f..c21e97212835c 100644 --- a/x-pack/solutions/observability/plugins/logs_explorer/common/data_views/models/data_view_descriptor.ts +++ b/x-pack/solutions/observability/plugins/logs_explorer/common/data_views/models/data_view_descriptor.ts @@ -11,7 +11,7 @@ import { DataViewSpecWithId } from '../../data_source_selection'; import { DataViewDescriptorType } from '../types'; const LOGS_ALLOWED_LIST = [ - createRegExpPatternFrom(DEFAULT_ALLOWED_LOGS_BASE_PATTERNS), + createRegExpPatternFrom(DEFAULT_ALLOWED_LOGS_BASE_PATTERNS, 'data'), // Add more strings or regex patterns as needed ]; @@ -59,7 +59,7 @@ export class DataViewDescriptor { testAgainstAllowedList(allowedList: string[]) { return this.title - ? testPatternAgainstAllowedList([createRegExpPatternFrom(allowedList)])(this.title) + ? testPatternAgainstAllowedList([createRegExpPatternFrom(allowedList, 'data')])(this.title) : false; } diff --git a/x-pack/solutions/observability/plugins/logs_explorer/common/hashed_cache.ts b/x-pack/solutions/observability/plugins/logs_explorer/common/hashed_cache.ts index 4b5ac5c614472..0cb68f0b31cc1 100644 --- a/x-pack/solutions/observability/plugins/logs_explorer/common/hashed_cache.ts +++ b/x-pack/solutions/observability/plugins/logs_explorer/common/hashed_cache.ts @@ -13,7 +13,7 @@ export interface IHashedCache { reset(): void; } -export class HashedCache { +export class HashedCache { private cache: LRUCache; constructor(options: LRUCache.Options = { max: 500 }) { diff --git a/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/README.md b/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/README.md index 5b16b7ba76abc..ed9c0125274cf 100644 --- a/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/README.md +++ b/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/README.md @@ -24,7 +24,9 @@ This tool is developed for our team working on the Elastic Observability platfor This will evaluate all existing scenarios, and write the evaluation results to the terminal. #### To run the evaluation using a hosted deployment: + - Add the credentials of Elasticsearch to `kibana.dev.yml` as follows: + ``` elasticsearch.hosts: https://: elasticsearch.username: @@ -32,6 +34,7 @@ elasticsearch.password: elasticsearch.ssl.verificationMode: none elasticsearch.ignoreVersionMismatch: true ``` + - Start Kibana - Run this command to start evaluating: `node x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/index.js --kibana http://:@localhost:5601` @@ -41,6 +44,7 @@ E.g.: `node x-pack/solutions/observability/plugins/observability_ai_assistant_ap The `--kibana` and `--es` flags override the default credentials. Only basic auth is supported. ## Other (optional) configuration flags + - `--connectorId` - Specify a generative AI connector to use. If none are given, it will prompt you to select a connector based on the ones that are available. If only a single supported connector is found, it will be used without prompting. - `--evaluateWith`: The connector ID to evaluate with. Leave empty to use the same connector, use "other" to get a selection menu. - `--spaceId` - Specify the space ID if you want to use a specific space. diff --git a/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/cli.ts b/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/cli.ts index 23fb67f77bbd7..9373abf13f91d 100644 --- a/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/cli.ts +++ b/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/cli.ts @@ -25,8 +25,8 @@ export const elasticsearchOption = { describe: 'Where Elasticsearch is running', string: true as const, default: format({ - ...parse(config['elasticsearch.hosts']), - auth: `${config['elasticsearch.username']}:${config['elasticsearch.password']}`, + ...parse(config.elasticsearch.hosts || 'http://localhost:9200'), + auth: `${config.elasticsearch.username}:${config.elasticsearch.password}`, }), }; diff --git a/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/kibana_client.ts b/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/kibana_client.ts index ef4d3988679fa..7b078d4cb5fc9 100644 --- a/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/kibana_client.ts +++ b/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/kibana_client.ts @@ -25,7 +25,7 @@ import { throwSerializedChatCompletionErrors } from '@kbn/observability-ai-assis import { Message, MessageRole } from '@kbn/observability-ai-assistant-plugin/common'; import { streamIntoObservable } from '@kbn/observability-ai-assistant-plugin/server'; import { ToolingLog } from '@kbn/tooling-log'; -import axios, { AxiosInstance, AxiosResponse, isAxiosError } from 'axios'; +import axios, { AxiosInstance, AxiosResponse, isAxiosError, AxiosRequestConfig } from 'axios'; import { omit, pick, remove } from 'lodash'; import pRetry from 'p-retry'; import { @@ -81,6 +81,7 @@ export interface ChatClient { ) => Promise; getResults: () => EvaluationResult[]; onResult: (cb: (result: EvaluationResult) => void) => () => void; + getConnectorId: () => string; } export class KibanaClient { @@ -93,6 +94,7 @@ export class KibanaClient { this.axios = axios.create({ headers: { 'kbn-xsrf': 'foo', + 'x-elastic-internal-origin': 'kibana', }, }); } @@ -118,17 +120,15 @@ export class KibanaClient { callKibana( method: string, props: { query?: UrlObject['query']; pathname: string; ignoreSpaceId?: boolean }, - data?: any + data?: any, + axiosParams: Partial = {} ) { const url = this.getUrl(props); return this.axios({ method, url, ...(method.toLowerCase() === 'delete' && !data ? {} : { data: data || {} }), - headers: { - 'kbn-xsrf': 'true', - 'x-elastic-internal-origin': 'Kibana', - }, + ...axiosParams, }).catch((error) => { if (isAxiosError(error)) { const interestingPartsOfError = { @@ -635,6 +635,7 @@ export class KibanaClient { onResultCallbacks.push({ callback, unregister }); return unregister; }, + getConnectorId: () => connectorId, }; } diff --git a/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/read_kibana_config.ts b/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/read_kibana_config.ts index e6a44cbb4a549..66fb66bf06aeb 100644 --- a/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/read_kibana_config.ts +++ b/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/read_kibana_config.ts @@ -9,6 +9,7 @@ import path from 'path'; import fs from 'fs'; import yaml from 'js-yaml'; import { identity, pickBy } from 'lodash'; +import { unflattenObject } from '@kbn/observability-utils-common/object/unflatten_object'; export type KibanaConfig = ReturnType; @@ -35,10 +36,14 @@ export const readKibanaConfig = () => { }; return { - 'elasticsearch.hosts': 'http://localhost:9200', - 'elasticsearch.username': 'elastic', - 'elasticsearch.password': 'changeme', - ...loadedKibanaConfig, - ...cliEsCredentials, + elasticsearch: { + hosts: 'http://localhost:9200', + username: 'elastic', + password: 'changeme', + }, + ...unflattenObject({ + ...loadedKibanaConfig, + ...cliEsCredentials, + }), }; }; diff --git a/x-pack/solutions/observability/plugins/observability_ai_assistant_app/server/functions/alerts.ts b/x-pack/solutions/observability/plugins/observability_ai_assistant_app/server/functions/alerts.ts index bf797bb170606..fda783c187b46 100644 --- a/x-pack/solutions/observability/plugins/observability_ai_assistant_app/server/functions/alerts.ts +++ b/x-pack/solutions/observability/plugins/observability_ai_assistant_app/server/functions/alerts.ts @@ -117,6 +117,7 @@ export function registerAlertsFunction({ functionCall, functions: nextFunctions, signal, + stream: true, }); }, }); diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/auto_detect.spec.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/auto_detect.spec.ts index cff927a2061c1..dd86abc0ee08e 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/auto_detect.spec.ts +++ b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/auto_detect.spec.ts @@ -36,6 +36,19 @@ test('Auto-detect logs and metrics', async ({ page, onboardingHomePage, autoDete fs.writeFileSync(outputPath, clipboardData); await autoDetectFlowPage.assertReceivedDataIndicator(); + + /** + * Host Details page sometime shows "No Data" + * even when we've detected data during + * the onboarding flow. This is most prominent + * in a test script which click on the "Explore Data" + * CTA immediately. Having a timeout before going + * to the Host Details page "solves" the issue. + * 2 minutes is generous and should be more then enough + * for the data to propagate everywhere. + */ + await page.waitForTimeout(2 * 60000); + await autoDetectFlowPage.clickAutoDetectSystemIntegrationCTA(); /** @@ -44,22 +57,5 @@ test('Auto-detect logs and metrics', async ({ page, onboardingHomePage, autoDete */ const hostDetailsPage = new HostDetailsPage(await page.waitForEvent('popup')); - /** - * There is a glitch on the Hosts page where it can show "No data" - * screen even though data is available and it can show it with a delay - * after the Hosts page layout was loaded. This workaround waits for - * the No Data screen to be visible, and if so - reloads the page. - * If the No Data screen does not appear, the test can proceed normally. - * Seems like some caching issue with the Hosts page. - */ - try { - await hostDetailsPage.noData().waitFor({ state: 'visible', timeout: 10000 }); - await hostDetailsPage.page.waitForTimeout(2000); - await hostDetailsPage.page.reload(); - } catch { - /* Ignore if "No Data" screen never showed up */ - } - - await hostDetailsPage.clickHostDetailsLogsTab(); - await hostDetailsPage.assertHostDetailsLogsStream(); + await hostDetailsPage.assertCpuPercentageNotEmpty(); }); diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/fixtures/base_page.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/fixtures/base_page.ts index e10be1d60cc1c..83a5dd5e32ea2 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/fixtures/base_page.ts +++ b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/fixtures/base_page.ts @@ -12,6 +12,8 @@ import { SpaceSelector } from '../pom/components/space_selector.component'; import { KubernetesOverviewDashboardPage } from '../pom/pages/kubernetes_overview_dashboard.page'; import { AutoDetectFlowPage } from '../pom/pages/auto_detect_flow.page'; import { KubernetesEAFlowPage } from '../pom/pages/kubernetes_ea_flow.page'; +import { OtelKubernetesFlowPage } from '../pom/pages/otel_kubernetes_flow.page'; +import { OtelKubernetesOverviewDashboardPage } from '../pom/pages/otel_kubernetes_overview_dashboard.page'; export const test = base.extend<{ headerBar: HeaderBar; @@ -19,7 +21,9 @@ export const test = base.extend<{ onboardingHomePage: OnboardingHomePage; autoDetectFlowPage: AutoDetectFlowPage; kubernetesEAFlowPage: KubernetesEAFlowPage; + otelKubernetesFlowPage: OtelKubernetesFlowPage; kubernetesOverviewDashboardPage: KubernetesOverviewDashboardPage; + otelKubernetesOverviewDashboardPage: OtelKubernetesOverviewDashboardPage; }>({ headerBar: async ({ page }, use) => { await use(new HeaderBar(page)); @@ -41,7 +45,15 @@ export const test = base.extend<{ await use(new KubernetesEAFlowPage(page)); }, + otelKubernetesFlowPage: async ({ page }, use) => { + await use(new OtelKubernetesFlowPage(page)); + }, + kubernetesOverviewDashboardPage: async ({ page }, use) => { await use(new KubernetesOverviewDashboardPage(page)); }, + + otelKubernetesOverviewDashboardPage: async ({ page }, use) => { + await use(new OtelKubernetesOverviewDashboardPage(page)); + }, }); diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/kubernetes_ea.spec.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/kubernetes_ea.spec.ts index 8478630b232f0..fbae86548efe5 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/kubernetes_ea.spec.ts +++ b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/kubernetes_ea.spec.ts @@ -45,22 +45,19 @@ test('Kubernetes EA', async ({ fs.writeFileSync(outputPath, clipboardData); await kubernetesEAFlowPage.assertReceivedDataIndicatorKubernetes(); - await kubernetesEAFlowPage.clickKubernetesAgentCTA(); - await kubernetesOverviewDashboardPage.openNodesInspector(); /** * There might be a case that dashboard still does not show * the data even though it was ingested already. This usually - * happens during in the test when navigation from the onboarding + * happens during the test when navigation from the onboarding * flow to the dashboard happens almost immediately. - * Waiting for a few seconds and reloading the page handles - * this case and makes the test a bit more robust. + * Having a timeout before going to the dashboard "solves" + * the issue. 2 minutes is generous and should be more then enough + * for the data to propagate everywhere. */ - try { - await kubernetesOverviewDashboardPage.assertNodesNoResultsNotVisible(); - } catch { - await kubernetesOverviewDashboardPage.page.waitForTimeout(2000); - await kubernetesOverviewDashboardPage.page.reload(); - } - await kubernetesOverviewDashboardPage.assetNodesInspectorStatusTableCells(); + await page.waitForTimeout(2 * 60000); + + await kubernetesEAFlowPage.clickKubernetesAgentCTA(); + + await kubernetesOverviewDashboardPage.assertNodesPanelNotEmpty(); }); diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/kubernetes_otel.spec.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/kubernetes_otel.spec.ts new file mode 100644 index 0000000000000..de24a025e16ed --- /dev/null +++ b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/kubernetes_otel.spec.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 fs from 'node:fs'; +import path from 'node:path'; +import { test } from './fixtures/base_page'; +import { assertEnv } from '../lib/assert_env'; + +test.beforeEach(async ({ page }) => { + await page.goto(`${process.env.KIBANA_BASE_URL}/app/observabilityOnboarding`); +}); + +test('Otel Kubernetes', async ({ + page, + onboardingHomePage, + otelKubernetesFlowPage, + otelKubernetesOverviewDashboardPage, +}) => { + assertEnv(process.env.ARTIFACTS_FOLDER, 'ARTIFACTS_FOLDER is not defined.'); + + const fileName = 'code_snippet_otel_kubernetes.sh'; + const outputPath = path.join(__dirname, '..', process.env.ARTIFACTS_FOLDER, fileName); + + await onboardingHomePage.selectKubernetesUseCase(); + await onboardingHomePage.selectOtelKubernetesQuickstart(); + + await otelKubernetesFlowPage.copyHelmRepositorySnippetToClipboard(); + const helmRepoSnippet = (await page.evaluate('navigator.clipboard.readText()')) as string; + + await otelKubernetesFlowPage.copyInstallStackSnippetToClipboard(); + const installStackSnippet = (await page.evaluate('navigator.clipboard.readText()')) as string; + + const codeSnippet = `${helmRepoSnippet}\n${installStackSnippet}`; + + /** + * Ensemble story watches for the code snippet file + * to be created and then executes it + */ + fs.writeFileSync(outputPath, codeSnippet); + + /** + * There is no explicit data ingest indication + * in the flow, so we need to rely on a timeout. + * 3 minutes should be enough for the stack to be + * created and to start pushing data. + */ + await page.waitForTimeout(3 * 60000); + + await otelKubernetesFlowPage.clickClusterOverviewDashboardCTA(); + await otelKubernetesOverviewDashboardPage.assertNodesPanelNotEmpty(); +}); diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/auto_detect_flow.page.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/auto_detect_flow.page.ts index b1090b3cf091d..49f1f34ea0936 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/auto_detect_flow.page.ts +++ b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/auto_detect_flow.page.ts @@ -5,47 +5,46 @@ * 2.0. */ -import { expect, Page } from '@playwright/test'; +import { expect, type Page, type Locator } from '@playwright/test'; export class AutoDetectFlowPage { page: Page; + private readonly copyToClipboardButton: Locator; + private readonly receivedDataIndicator: Locator; + private readonly autoDetectSystemIntegrationActionLink: Locator; + private readonly codeBlock: Locator; + constructor(page: Page) { this.page = page; - } - - private readonly copyToClipboardButton = () => - this.page.getByTestId('observabilityOnboardingCopyToClipboardButton'); - - private readonly receivedDataIndicator = () => - this.page + this.copyToClipboardButton = this.page.getByTestId( + 'observabilityOnboardingCopyToClipboardButton' + ); + this.receivedDataIndicator = this.page .getByTestId('observabilityOnboardingAutoDetectPanelDataReceivedProgressIndicator') .getByText('Your data is ready to explore!'); - - private readonly autoDetectSystemIntegrationActionLink = () => - this.page.getByTestId( + this.autoDetectSystemIntegrationActionLink = this.page.getByTestId( 'observabilityOnboardingDataIngestStatusActionLink-inventory-host-details' ); - - private readonly codeBlock = () => - this.page.getByTestId('observabilityOnboardingAutoDetectPanelCodeSnippet'); + this.codeBlock = this.page.getByTestId('observabilityOnboardingAutoDetectPanelCodeSnippet'); + } public async copyToClipboard() { - await this.copyToClipboardButton().click(); + await this.copyToClipboardButton.click(); } public async assertVisibilityCodeBlock() { - await expect(this.codeBlock(), 'Code block should be visible').toBeVisible(); + await expect(this.codeBlock, 'Code block should be visible').toBeVisible(); } public async assertReceivedDataIndicator() { await expect( - this.receivedDataIndicator(), + this.receivedDataIndicator, 'Received data indicator should be visible' ).toBeVisible(); } public async clickAutoDetectSystemIntegrationCTA() { - await this.autoDetectSystemIntegrationActionLink().click(); + await this.autoDetectSystemIntegrationActionLink.click(); } } diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/host_details.page.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/host_details.page.ts index d22b33d851639..ce6c09cc911a2 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/host_details.page.ts +++ b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/host_details.page.ts @@ -5,34 +5,23 @@ * 2.0. */ -import { expect, Page } from '@playwright/test'; +import { expect, type Page, type Locator } from '@playwright/test'; export class HostDetailsPage { page: Page; - public readonly hostDetailsLogsTab = () => this.page.getByTestId('infraAssetDetailsLogsTab'); - - private readonly hostDetailsLogsStream = () => this.page.getByTestId('logStream'); - - public readonly noData = () => this.page.getByTestId('kbnNoDataPage'); + private readonly cpuPercentageValue: Locator; constructor(page: Page) { this.page = page; - } - public async clickHostDetailsLogsTab() { - await this.hostDetailsLogsTab().click(); + this.cpuPercentageValue = this.page + .getByTestId('infraAssetDetailsKPIcpuUsage') + .locator('.echMetricText__value'); } - public async assertHostDetailsLogsStream() { - await expect( - this.hostDetailsLogsStream(), - 'Host details log stream should be visible' - /** - * Using toBeAttached() instead of toBeVisible() because the element - * we're selecting here has a bit weird layout with 0 height and - * overflowing child elements. 0 height makes toBeVisible() fail. - */ - ).toBeAttached(); + public async assertCpuPercentageNotEmpty() { + await expect(this.cpuPercentageValue).toBeVisible(); + expect(await this.cpuPercentageValue.textContent()).toMatch(/\d+%$/); } } diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/kubernetes_ea_flow.page.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/kubernetes_ea_flow.page.ts index e956de4855579..82ad9ac6ac854 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/kubernetes_ea_flow.page.ts +++ b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/kubernetes_ea_flow.page.ts @@ -5,47 +5,47 @@ * 2.0. */ -import { expect, Page } from '@playwright/test'; +import { expect, type Page, type Locator } from '@playwright/test'; export class KubernetesEAFlowPage { page: Page; + private readonly receivedDataIndicatorKubernetes: Locator; + private readonly kubernetesAgentExploreDataActionLink: Locator; + private readonly codeBlock: Locator; + private readonly copyToClipboardButton: Locator; + constructor(page: Page) { this.page = page; - } - private readonly receivedDataIndicatorKubernetes = () => - this.page + this.receivedDataIndicatorKubernetes = this.page .getByTestId('observabilityOnboardingKubernetesPanelDataProgressIndicator') .getByText('We are monitoring your cluster'); - - private readonly kubernetesAgentExploreDataActionLink = () => - this.page.getByTestId( + this.kubernetesAgentExploreDataActionLink = this.page.getByTestId( 'observabilityOnboardingDataIngestStatusActionLink-kubernetes-f4dc26db-1b53-4ea2-a78b-1bfab8ea267c' ); - - private readonly codeBlock = () => - this.page.getByTestId('observabilityOnboardingKubernetesPanelCodeSnippet'); - - private readonly copyToClipboardButton = () => - this.page.getByTestId('observabilityOnboardingCopyToClipboardButton'); + this.codeBlock = this.page.getByTestId('observabilityOnboardingKubernetesPanelCodeSnippet'); + this.copyToClipboardButton = this.page.getByTestId( + 'observabilityOnboardingCopyToClipboardButton' + ); + } public async assertVisibilityCodeBlock() { - await expect(this.codeBlock(), 'Code block should be visible').toBeVisible(); + await expect(this.codeBlock, 'Code block should be visible').toBeVisible(); } public async copyToClipboard() { - await this.copyToClipboardButton().click(); + await this.copyToClipboardButton.click(); } public async assertReceivedDataIndicatorKubernetes() { await expect( - this.receivedDataIndicatorKubernetes(), + this.receivedDataIndicatorKubernetes, 'Received data indicator should be visible' ).toBeVisible(); } public async clickKubernetesAgentCTA() { - await this.kubernetesAgentExploreDataActionLink().click(); + await this.kubernetesAgentExploreDataActionLink.click(); } } diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/kubernetes_overview_dashboard.page.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/kubernetes_overview_dashboard.page.ts index 9562f0262994f..1059d0793f6c2 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/kubernetes_overview_dashboard.page.ts +++ b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/kubernetes_overview_dashboard.page.ts @@ -5,44 +5,22 @@ * 2.0. */ -import { expect, Page } from '@playwright/test'; +import { expect, type Page, type Locator } from '@playwright/test'; export class KubernetesOverviewDashboardPage { page: Page; + private readonly nodesPanelChart: Locator; + constructor(page: Page) { this.page = page; - } - - private readonly nodesPanelHeader = () => this.page.getByTestId('embeddablePanelHeading-Nodes'); - - private readonly nodesInspectorButton = () => - this.page - .getByTestId('embeddablePanelHoverActions-Nodes') - .getByTestId('embeddablePanelAction-openInspector'); - - private readonly nodesInspectorTableNoResults = () => - this.page.getByTestId('inspectorTable').getByText('No items found'); - - private readonly nodesInspectorTableStatusTableCells = () => - this.page.getByTestId('inspectorTable').getByText('Status'); - - public async assertNodesNoResultsNotVisible() { - await expect( - this.nodesInspectorTableNoResults(), - 'Nodes "No results" message should not be visible' - ).toBeHidden(); - } - public async openNodesInspector() { - await this.nodesPanelHeader().hover(); - await this.nodesInspectorButton().click(); + this.nodesPanelChart = this.page + .locator(`#panel-7116207b-48ce-4d93-9fbd-26d73af1c185`) + .getByTestId('xyVisChart'); } - public async assetNodesInspectorStatusTableCells() { - await expect( - this.nodesInspectorTableStatusTableCells(), - 'Status table cell should exist' - ).toBeVisible(); + async assertNodesPanelNotEmpty() { + await expect(this.nodesPanelChart).toBeVisible(); } } diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/onboarding_home.page.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/onboarding_home.page.ts index 6997001496521..4b04507d27f04 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/onboarding_home.page.ts +++ b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/onboarding_home.page.ts @@ -5,40 +5,50 @@ * 2.0. */ -import { Page } from '@playwright/test'; +import type { Page, Locator } from '@playwright/test'; export class OnboardingHomePage { page: Page; + private readonly otelKubernetesQuickStartCard: Locator; + private readonly useCaseKubernetes: Locator; + private readonly kubernetesQuickStartCard: Locator; + private readonly useCaseHost: Locator; + private readonly autoDetectElasticAgent: Locator; + constructor(page: Page) { this.page = page; - } - - private readonly useCaseKubernetes = () => - this.page.getByTestId('observabilityOnboardingUseCaseCard-kubernetes').getByRole('radio'); - - private readonly kubernetesQuickStartCard = () => - this.page.getByTestId('integration-card:kubernetes-quick-start'); - private readonly useCaseHost = () => - this.page.getByTestId('observabilityOnboardingUseCaseCard-host').getByRole('radio'); - - private readonly autoDetectElasticAgent = () => - this.page.getByTestId('integration-card:auto-detect-logs'); + this.otelKubernetesQuickStartCard = this.page.getByTestId('integration-card:otel-kubernetes'); + this.useCaseKubernetes = this.page + .getByTestId('observabilityOnboardingUseCaseCard-kubernetes') + .getByRole('radio'); + this.kubernetesQuickStartCard = this.page.getByTestId( + 'integration-card:kubernetes-quick-start' + ); + this.useCaseHost = this.page + .getByTestId('observabilityOnboardingUseCaseCard-host') + .getByRole('radio'); + this.autoDetectElasticAgent = this.page.getByTestId('integration-card:auto-detect-logs'); + } public async selectHostUseCase() { - await this.useCaseHost().click(); + await this.useCaseHost.click(); } public async selectKubernetesUseCase() { - await this.useCaseKubernetes().click(); + await this.useCaseKubernetes.click(); } public async selectAutoDetectWithElasticAgent() { - await this.autoDetectElasticAgent().click(); + await this.autoDetectElasticAgent.click(); } public async selectKubernetesQuickstart() { - await this.kubernetesQuickStartCard().click(); + await this.kubernetesQuickStartCard.click(); + } + + public async selectOtelKubernetesQuickstart() { + await this.otelKubernetesQuickStartCard.click(); } } diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/otel_kubernetes_flow.page.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/otel_kubernetes_flow.page.ts new file mode 100644 index 0000000000000..8c5362f0dac17 --- /dev/null +++ b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/otel_kubernetes_flow.page.ts @@ -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 { Page } from '@playwright/test'; + +export class OtelKubernetesFlowPage { + page: Page; + + constructor(page: Page) { + this.page = page; + } + + public async copyHelmRepositorySnippetToClipboard() { + await this.page + .getByTestId('observabilityOnboardingOtelKubernetesPanelAddRepositoryCopyToClipboard') + .click(); + } + + public async copyInstallStackSnippetToClipboard() { + await this.page + .getByTestId('observabilityOnboardingOtelKubernetesPanelInstallStackCopyToClipboard') + .click(); + } + + public async clickClusterOverviewDashboardCTA() { + await this.page + .getByTestId( + 'observabilityOnboardingDataIngestStatusActionLink-kubernetes_otel-cluster-overview' + ) + .click(); + } +} diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/otel_kubernetes_overview_dashboard.page.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/otel_kubernetes_overview_dashboard.page.ts new file mode 100644 index 0000000000000..f7159632ef0d9 --- /dev/null +++ b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/playwright/stateful/pom/pages/otel_kubernetes_overview_dashboard.page.ts @@ -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 { expect, type Page, type Locator } from '@playwright/test'; + +export class OtelKubernetesOverviewDashboardPage { + page: Page; + + private readonly nodesPanelValue: Locator; + + constructor(page: Page) { + this.page = page; + + this.nodesPanelValue = this.page.locator( + `#panel-6119419c-1899-4765-aed4-c050cde4c30a .echMetricText__value` + ); + } + + async assertNodesPanelNotEmpty() { + await expect(this.nodesPanelValue).toBeVisible(); + expect(await this.nodesPanelValue.textContent()).toMatch(/\d+/); + } +} diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/onboarding_flow_form/onboarding_flow_form.tsx b/x-pack/solutions/observability/plugins/observability_onboarding/public/application/onboarding_flow_form/onboarding_flow_form.tsx index eb5ee3bc92369..b1c5da970a78b 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/onboarding_flow_form/onboarding_flow_form.tsx +++ b/x-pack/solutions/observability/plugins/observability_onboarding/public/application/onboarding_flow_form/onboarding_flow_form.tsx @@ -335,8 +335,8 @@ export const OnboardingFlowForm: FunctionComponent = () => { flowSearch={integrationSearch} setSearchQuery={setIntegrationSearch} flowCategory={searchParams.get('category')} - customCards={customCards - ?.filter( + customCards={(customCards || []) + .filter( // Filter out collection cards and regular integrations that show up via search anyway (card) => card.type === 'virtual' && !card.isCollectionCard ) diff --git a/x-pack/solutions/observability/plugins/observability_shared/public/components/add_data_panel/index.tsx b/x-pack/solutions/observability/plugins/observability_shared/public/components/add_data_panel/index.tsx index f047fdb6b33d3..6cafcafaf44a2 100644 --- a/x-pack/solutions/observability/plugins/observability_shared/public/components/add_data_panel/index.tsx +++ b/x-pack/solutions/observability/plugins/observability_shared/public/components/add_data_panel/index.tsx @@ -8,6 +8,7 @@ /* eslint-disable @elastic/eui/href-or-on-click */ import { + COLOR_MODES_STANDARD, EuiButton, EuiButtonIcon, EuiFlexGroup, @@ -22,7 +23,6 @@ import { } from '@elastic/eui'; import React from 'react'; import { i18n } from '@kbn/i18n'; -import { useTheme } from '../../hooks/use_theme'; interface AddDataPanelContent { title: string; @@ -78,11 +78,10 @@ export function AddDataPanel({ onAddData, 'data-test-subj': dataTestSubj, }: AddDataPanelProps) { - const { euiTheme } = useEuiTheme(); - const theme = useTheme(); - const imgSrc = `${content.img?.baseFolderPath}/${theme.darkMode ? 'dark' : 'light'}/${ - content.img?.name - }`; + const { euiTheme, colorMode } = useEuiTheme(); + const imgSrc = `${content.img?.baseFolderPath}/${ + colorMode === COLOR_MODES_STANDARD.dark ? 'dark' : 'light' + }/${content.img?.name}`; return ( <> diff --git a/x-pack/solutions/observability/plugins/profiling/README.md b/x-pack/solutions/observability/plugins/profiling/README.md index b41613c8e3e87..e81faaf4a1ca1 100644 --- a/x-pack/solutions/observability/plugins/profiling/README.md +++ b/x-pack/solutions/observability/plugins/profiling/README.md @@ -51,28 +51,23 @@ The E2E tests are located in [`x-pack/solutions/observability/plugins/profiling/ Universal Profiling uses [FTR](../../../../packages/kbn-test/README.mdx) (functional test runner) and [Cypress](https://www.cypress.io/) to run the e2e tests. The tests are located at `kibana/x-pack/solutions/observability/plugins/profiling/e2e/cypress/e2e`. -### Start test server - -``` -node x-pack/solutions/observability/plugins/profiling/scripts/test/e2e --server -``` - -### Open cypress dashboard +### Start with Cypress Dashboard ``` node x-pack/solutions/observability/plugins/profiling/scripts/test/e2e --open ``` -### Run tests in terminal +### Run tests +Runs all tests in the terminal ``` -node x-pack/solutions/observability/plugins/profiling/scripts/test/e2e --runner +node x-pack/solutions/observability/plugins/profiling/scripts/test/e2e ``` -### Run like CI +### Run tests in headed mode ``` -node x-pack/solutions/observability/plugins/profiling/scripts/test/e2e +node x-pack/solutions/observability/plugins/profiling/scripts/test/e2e --headed ``` ## Other resources diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/README.md b/x-pack/solutions/observability/plugins/profiling/e2e/README.md index ab0e33ed71d7c..dfc1639db6bca 100644 --- a/x-pack/solutions/observability/plugins/profiling/e2e/README.md +++ b/x-pack/solutions/observability/plugins/profiling/e2e/README.md @@ -11,41 +11,35 @@ Tests run on buildkite PR pipeline are parallelized (4 parallel jobs) and are or ```yml ... depends_on: build - parallelism: 4 + parallelism: 3 ... ``` ## Running it locally -### Start test server +### Start with Cypress Dashboard ``` -node x-pack/solutions/observability/plugins/profiling/scripts/test/e2e --server +node x-pack/solutions/observability/plugins/profiling/scripts/test/e2e --open ``` ### Run tests Runs all tests in the terminal ``` -node x-pack/solutions/observability/plugins/profiling/scripts/test/e2e --runner +node x-pack/solutions/observability/plugins/profiling/scripts/test/e2e ``` -### Open cypress dashboard -Opens cypress dashboard, there it's possible to select what test you want to run. +### Run tests in headed mode ``` -node x-pack/solutions/observability/plugins/profiling/scripts/test/e2e --open +node x-pack/solutions/observability/plugins/profiling/scripts/test/e2e --headed ``` + ### Arguments | Option | Description | | ------------ | ----------------------------------------------- | -| --server | Only start ES and Kibana | -| --runner | Only run tests | -| --spec | Specify the specs to run | -| --times | Repeat the test n number of times | -| --bail | stop tests after the first failure | +| --open | Opens Cypress dashboard | +| --headed | Runs tests in headed mode | -``` -node x-pack/solutions/observability/plugins/profiling/scripts/test/e2e.js --runner --spec cypress/e2e/profiling.cy.ts --times 2 -``` diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/cypress.config.ts b/x-pack/solutions/observability/plugins/profiling/e2e/cypress.config.ts index afbad0bac67d0..c66dcc5cd01e3 100644 --- a/x-pack/solutions/observability/plugins/profiling/e2e/cypress.config.ts +++ b/x-pack/solutions/observability/plugins/profiling/e2e/cypress.config.ts @@ -8,25 +8,27 @@ import { defineCypressConfig } from '@kbn/cypress-config'; export default defineCypressConfig({ + reporter: '../../../../../../node_modules/cypress-multi-reporters', + reporterOptions: { + configFile: './reporter_config.json', + }, fileServerFolder: './cypress', fixturesFolder: './cypress/fixtures', screenshotsFolder: './cypress/screenshots', videosFolder: './cypress/videos', - requestTimeout: 10000, - responseTimeout: 40000, - defaultCommandTimeout: 30000, + defaultCommandTimeout: 60000, execTimeout: 120000, pageLoadTimeout: 120000, viewportHeight: 1800, viewportWidth: 1440, video: false, - screenshotOnRunFailure: false, - retries: { - runMode: 1, - }, + screenshotOnRunFailure: true, e2e: { baseUrl: 'http://localhost:5601', supportFile: './cypress/support/e2e.ts', - specPattern: './cypress/e2e/**/*.cy.{js,jsx,ts,tsx}', + specPattern: './cypress/e2e/**/*.cy.ts', + experimentalMemoryManagement: true, + numTestsKeptInMemory: 3, + experimentalRunAllSpecs: true, }, }); diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/cypress/.gitignore b/x-pack/solutions/observability/plugins/profiling/e2e/cypress/.gitignore new file mode 100644 index 0000000000000..d501d1d6d3262 --- /dev/null +++ b/x-pack/solutions/observability/plugins/profiling/e2e/cypress/.gitignore @@ -0,0 +1,3 @@ +/videos/* +/screenshots/* +/downloads/* diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/cypress/support/commands.ts b/x-pack/solutions/observability/plugins/profiling/e2e/cypress/support/commands.ts index ada8681d308d8..64fe0dfcb697e 100644 --- a/x-pack/solutions/observability/plugins/profiling/e2e/cypress/support/commands.ts +++ b/x-pack/solutions/observability/plugins/profiling/e2e/cypress/support/commands.ts @@ -59,14 +59,13 @@ Cypress.Commands.add( 'addKqlFilter', ({ key, value, dataTestSubj = 'profilingUnifiedSearchBar', waitForSuggestion = true }) => { cy.getByTestSubj(dataTestSubj).type(key); - cy.contains(key); - cy.getByTestSubj(`autocompleteSuggestion-field-${key}-`).click(); - // Do not close quotes here as it will not display the suggestion box - cy.getByTestSubj(dataTestSubj).type(`: "${value}`); + + cy.getByTestSubj(`autocompleteSuggestion-field-${key}-`).should('be.visible'); + cy.getByTestSubj(dataTestSubj).type(` : ${value}`); if (waitForSuggestion) { - cy.getByTestSubj( - Cypress.$.escapeSelector(`autocompleteSuggestion-value-"${value}"-`) - ).click(); + cy.getByTestSubj(`autocompleteSuggestion-value-\\"${value}\\"-`) + .should('be.visible') + .click({ force: true }); } cy.getByTestSubj(dataTestSubj).type('{enter}'); } diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/cypress/support/e2e.ts b/x-pack/solutions/observability/plugins/profiling/e2e/cypress/support/e2e.ts index 93daa0bc7ed2a..5f5d1eb3b3614 100644 --- a/x-pack/solutions/observability/plugins/profiling/e2e/cypress/support/e2e.ts +++ b/x-pack/solutions/observability/plugins/profiling/e2e/cypress/support/e2e.ts @@ -10,4 +10,3 @@ Cypress.on('uncaught:exception', (err, runnable) => { }); import './commands'; -// import './output_command_timings'; diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/ftr_config_open.ts b/x-pack/solutions/observability/plugins/profiling/e2e/ftr_config_open.ts deleted file mode 100644 index b3c061c031ca4..0000000000000 --- a/x-pack/solutions/observability/plugins/profiling/e2e/ftr_config_open.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 { FtrConfigProviderContext } from '@kbn/test'; -import cypress from 'cypress'; -import type { FtrProviderContext } from './ftr_provider_context'; -import { cypressTestRunner } from './cypress_test_runner'; - -async function ftrConfigOpen({ readConfigFile }: FtrConfigProviderContext) { - const kibanaConfig = await readConfigFile(require.resolve('./ftr_config.ts')); - return { - ...kibanaConfig.getAll(), - testRunner, - }; -} - -export async function testRunner(ftrProviderContext: FtrProviderContext) { - await cypressTestRunner({ ftrProviderContext, cypressExecution: cypress.open }); -} - -// eslint-disable-next-line import/no-default-export -export default ftrConfigOpen; diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/ftr_config_runner.ts b/x-pack/solutions/observability/plugins/profiling/e2e/ftr_config_runner.ts deleted file mode 100644 index 38c69667213cf..0000000000000 --- a/x-pack/solutions/observability/plugins/profiling/e2e/ftr_config_runner.ts +++ /dev/null @@ -1,35 +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 { FtrConfigProviderContext } from '@kbn/test'; -import cypress from 'cypress'; -import { cypressTestRunner } from './cypress_test_runner'; -import type { FtrProviderContext } from './ftr_provider_context'; - -async function ftrConfigRun({ readConfigFile }: FtrConfigProviderContext) { - const kibanaConfig = await readConfigFile(require.resolve('./ftr_config.ts')); - - return { - ...kibanaConfig.getAll(), - testRunner, - }; -} - -async function testRunner(ftrProviderContext: FtrProviderContext) { - const result = await cypressTestRunner({ ftrProviderContext, cypressExecution: cypress.run }); - - if ( - result && - ((result as CypressCommandLine.CypressFailedRunResult)?.status === 'failed' || - (result as CypressCommandLine.CypressRunResult)?.totalFailed) - ) { - process.exitCode = 1; - } -} - -// eslint-disable-next-line import/no-default-export -export default ftrConfigRun; diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/package.json b/x-pack/solutions/observability/plugins/profiling/e2e/package.json new file mode 100644 index 0000000000000..2bc70d1057d20 --- /dev/null +++ b/x-pack/solutions/observability/plugins/profiling/e2e/package.json @@ -0,0 +1,15 @@ +{ + "author": "Elastic", + "name": "@kbn/profiling-ftr-e2e", + "version": "1.0.0", + "private": true, + "license": "Elastic License 2.0", + "scripts": { + "cypress": "NODE_OPTIONS=--openssl-legacy-provider node ../../../../security/plugins/security_solution/scripts/start_cypress_parallel --config-file ../observability/plugins/profiling/e2e/cypress.config.ts --ftr-config-file ../../../../../test/profiling_cypress/cli_config", + "cypress:open": "yarn cypress open", + "cypress:run": "yarn cypress run", + "cypress:run:headed": "yarn cypress run --headed", + "junit:merge": "../../../../../../node_modules/.bin/mochawesome-merge ../../../../../../target/kibana-profiling/cypress/results/mochawesome*.json > ../../../../../../target/kibana-profiling/cypress/results/output.json && ../../../../../../node_modules/.bin/marge ../../../../../../target/kibana-profiling/cypress/results/output.json --reportDir ../../../../../../target/kibana-profiling/cypress/results && yarn junit:transform && mkdir -p ../../../../../../target/junit && cp ../../../../../../target/kibana-profiling/cypress/results/*.xml ../../../../../../target/junit/", + "junit:transform": "node ../../../../security/plugins/security_solution/scripts/junit_transformer --pathPattern '../../../../../../target/kibana-profiling/cypress/results/*.xml' --rootDirectory ../../../../../../ --reportName 'Profiling Cypress' --writeInPlace" + } +} \ No newline at end of file diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/reporter_config.json b/x-pack/solutions/observability/plugins/profiling/e2e/reporter_config.json new file mode 100644 index 0000000000000..6ca73aa805e0b --- /dev/null +++ b/x-pack/solutions/observability/plugins/profiling/e2e/reporter_config.json @@ -0,0 +1,10 @@ +{ + "reporterEnabled": "mochawesome, mocha-junit-reporter", + "reporterOptions": { + "html": false, + "json": true, + "mochaFile": "../../../../../../target/kibana-profiling/cypress/results/TEST-profiling-cypress-[hash].xml", + "overwrite": false, + "reportDir": "../../../../../../target/kibana-profiling/cypress/results" + } +} diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/tsconfig.json b/x-pack/solutions/observability/plugins/profiling/e2e/tsconfig.json index c87e2192fa985..db3456abbd422 100644 --- a/x-pack/solutions/observability/plugins/profiling/e2e/tsconfig.json +++ b/x-pack/solutions/observability/plugins/profiling/e2e/tsconfig.json @@ -9,11 +9,7 @@ }, "kbn_references": [ { "path": "../../../../test/tsconfig.json" }, - "@kbn/test", - "@kbn/dev-utils", "@kbn/cypress-config", "@kbn/observability-plugin", - "@kbn/ftr-common-functional-services", - "@kbn/ftr-common-functional-ui-services" ] } diff --git a/x-pack/solutions/observability/plugins/profiling/scripts/test/e2e.js b/x-pack/solutions/observability/plugins/profiling/scripts/test/e2e.js index fd2da7b56fb68..0302e0736da74 100644 --- a/x-pack/solutions/observability/plugins/profiling/scripts/test/e2e.js +++ b/x-pack/solutions/observability/plugins/profiling/scripts/test/e2e.js @@ -6,104 +6,42 @@ */ /* eslint-disable no-console */ -const { times } = require('lodash'); const path = require('path'); const yargs = require('yargs'); const childProcess = require('child_process'); -const { REPO_ROOT } = require('@kbn/repo-info'); const { argv } = yargs(process.argv.slice(2)) .parserConfiguration({ 'unknown-options-as-args': true }) - .option('kibana-install-dir', { - default: '', - type: 'string', - description: 'Path to the Kibana install directory', - }) - .option('server', { + .option('headed', { default: false, type: 'boolean', - description: 'Start Elasticsearch and Kibana', - }) - .option('runner', { - default: false, - type: 'boolean', - description: - 'Run all tests (an instance of Elasticsearch and kibana are needs to be available)', + description: 'Runs Cypress in headed mode', }) .option('open', { default: false, type: 'boolean', - description: - 'Open cypress dashboard (an instance of Elasticsearch and kibana are needs to be available)', - }) - .option('times', { - type: 'number', - description: 'Repeat the test n number of times', - }) - .option('bail', { - default: false, - type: 'boolean', - description: 'stop tests after the first failure', + description: 'Opens Cypress dashboard', }) .help(); const e2eDir = path.join(__dirname, '../../e2e'); -let ftrScript = 'functional_tests.js'; -if (argv.server) { - ftrScript = 'functional_tests_server.js'; -} else if (argv.runner || argv.open) { - ftrScript = 'functional_test_runner.js'; -} - -const cypressCliArgs = yargs(argv._).parserConfiguration({ - 'boolean-negation': false, -}).argv; - -if (cypressCliArgs.grep) { - throw new Error('--grep is not supported. Please use --spec instead'); -} - -const ftrConfig = argv.open ? './ftr_config_open.ts' : './ftr_config_runner.ts'; -const spawnArgs = [ - `${REPO_ROOT}/scripts/${ftrScript}`, - `--config=${ftrConfig}`, - `--kibana-install-dir=${argv.kibanaInstallDir}`, - ...(argv.bail ? [`--bail`] : []), -]; - function runTests() { - console.log(`Running e2e tests: "node ${spawnArgs.join(' ')}"`); + const mode = argv.open ? 'open' : 'run'; + const isHeaded = mode === 'run' && argv.headed ? ':headed' : ''; + + console.log(`Running e2e tests: "yarn cypress:${mode}${isHeaded}"`); - return childProcess.spawnSync('node', spawnArgs, { + return childProcess.spawnSync('yarn', [`cypress:${mode}${isHeaded}`], { cwd: e2eDir, - env: { - ...process.env, - CYPRESS_CLI_ARGS: JSON.stringify(cypressCliArgs), - NODE_OPTIONS: '--openssl-legacy-provider', - }, encoding: 'utf8', stdio: 'inherit', }); } -const runCounter = { succeeded: 0, failed: 0, remaining: argv.times }; let exitStatus = 0; -times(argv.times ?? 1, () => { - const child = runTests(); - if (child.status === 0) { - runCounter.succeeded++; - } else { - exitStatus = child.status; - runCounter.failed++; - } - - runCounter.remaining--; - - if (argv.times > 1) { - console.log(runCounter); - } -}); +const child = runTests(); +exitStatus = child.status; process.exitCode = exitStatus; console.log(`Quitting with exit code ${exitStatus}`); diff --git a/x-pack/solutions/observability/plugins/slo/common/constants.ts b/x-pack/solutions/observability/plugins/slo/common/constants.ts index 0e4c29070ec2c..b47fecdbd3144 100644 --- a/x-pack/solutions/observability/plugins/slo/common/constants.ts +++ b/x-pack/solutions/observability/plugins/slo/common/constants.ts @@ -54,7 +54,7 @@ export const SUPPRESSED_PRIORITY_ACTION = { }; export const SLO_MODEL_VERSION = 2; -export const SLO_RESOURCES_VERSION = 3.3; +export const SLO_RESOURCES_VERSION = 3.4; export const SLO_RESOURCES_VERSION_MAJOR = 3; export const SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME = '.slo-observability.sli-mappings'; diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slo_details/components/header_title.tsx b/x-pack/solutions/observability/plugins/slo/public/pages/slo_details/components/header_title.tsx index e0ca9efc079d1..116e116b354c9 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slo_details/components/header_title.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slo_details/components/header_title.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiFlexGroup, EuiFlexItem, EuiSkeletonText, EuiText } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiMarkdownFormat, EuiSkeletonText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { SLOWithSummaryResponse } from '@kbn/slo-schema'; import moment from 'moment'; @@ -37,30 +37,43 @@ export function HeaderTitle({ isLoading, slo }: Props) { - - - - {i18n.translate('xpack.slo.sloDetails.headerTitle.lastUpdatedMessage', { - defaultMessage: 'Last updated on', + + + + {i18n.translate('xpack.slo.sloDetails.headerTitle.lastUpdatedLabel', { + defaultMessage: '**Last updated by** {updatedBy} **on** {updatedAt}', + values: { + updatedBy: slo.updatedBy ?? NOT_AVAILABLE_LABEL, + updatedAt: moment(slo.updatedAt).format('ll'), + }, })} - -   - {moment(slo.updatedAt).format('ll')} - - - - - - {i18n.translate('xpack.slo.sloDetails.headerTitle.createdMessage', { - defaultMessage: 'Created on', + + + + + {i18n.translate('xpack.slo.sloDetails.headerTitle.createdLabel', { + defaultMessage: '**Created by** {createdBy} **on** {createdAt}', + values: { + createdBy: slo.createdBy ?? NOT_AVAILABLE_LABEL, + createdAt: moment(slo.createdAt).format('ll'), + }, })} - -   - {moment(slo.createdAt).format('ll')} - - + + + ); } + +const NOT_AVAILABLE_LABEL = i18n.translate('xpack.slo.sloDetails.headerTitle.notAvailableLabel', { + defaultMessage: 'n/a', +}); diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/card_view/slo_card_item.tsx b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/card_view/slo_card_item.tsx index b043111f3a9af..bbeff88553124 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/card_view/slo_card_item.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/card_view/slo_card_item.tsx @@ -149,8 +149,8 @@ export function SloCardItem({ slo, rules, activeAlerts, historicalSummary, refet `} title={ slo.summary.summaryUpdatedAt - ? i18n.translate('xpack.slo.sloCardItem.euiPanel.lastUpdatedLabel', { - defaultMessage: '{status}, Last updated: {value}', + ? i18n.translate('xpack.slo.sloCardItem.euiPanel.lastSummaryUpdatedLabel', { + defaultMessage: '{status}, Last summary updated: {value}', values: { status: slo.summary.status, value: moment(slo.summary.summaryUpdatedAt).fromNow(), diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/card_view/slo_card_item_instance_badge.tsx b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/card_view/slo_card_item_instance_badge.tsx index 64847a423b874..26854ee7ffc00 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/card_view/slo_card_item_instance_badge.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/card_view/slo_card_item_instance_badge.tsx @@ -41,7 +41,7 @@ export function SLOCardItemInstanceBadge({ slo }: Props) { data-test-subj="o11ySlosSeeAllInstanceIdsBadge" > {`${i18n.translate('xpack.slo.extraInstanceIds.badge', { - defaultMessage: '+{count, plural, one {# more instance} other {# more instances}}', + defaultMessage: '+{count, plural, one {# instance} other {# instances}}', values: { count: entries.length - 1, }, diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/common/slo_groupings.tsx b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/common/slo_groupings.tsx index 902e46d549e5b..dc7728a0e1f1d 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/common/slo_groupings.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/common/slo_groupings.tsx @@ -68,7 +68,7 @@ export function SLOGroupings({ slo, direction = 'row', gutterSize = 's', truncat {`(${i18n.translate('xpack.slo.andLabel', { defaultMessage: - 'and {count, plural, one {# more instance} other {# more instances}}', + 'and {count, plural, one {# instance} other {# instances}}', values: { count: rest.length, }, diff --git a/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slo_summary_mappings_template.ts b/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slo_summary_mappings_template.ts index d25722e4f323d..a130e45ade735 100644 --- a/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slo_summary_mappings_template.ts +++ b/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slo_summary_mappings_template.ts @@ -135,6 +135,20 @@ export const getSLOSummaryMappingsTemplate = ( }, }, }, + createdAt: { + type: 'date', + format: 'date_optional_time||epoch_millis', + }, + updatedAt: { + type: 'date', + format: 'date_optional_time||epoch_millis', + }, + createdBy: { + type: 'keyword', + }, + updatedBy: { + type: 'keyword', + }, }, }, sliValue: { diff --git a/x-pack/solutions/observability/plugins/slo/server/assets/ingest_templates/slo_summary_pipeline_template.ts b/x-pack/solutions/observability/plugins/slo/server/assets/ingest_templates/slo_summary_pipeline_template.ts index 7d51ffeddea4b..d269bdf1d6de9 100644 --- a/x-pack/solutions/observability/plugins/slo/server/assets/ingest_templates/slo_summary_pipeline_template.ts +++ b/x-pack/solutions/observability/plugins/slo/server/assets/ingest_templates/slo_summary_pipeline_template.ts @@ -234,6 +234,21 @@ export const getSLOSummaryPipelineTemplate = ( source: getBurnRateSource('oneDayBurnRate'), }, }, + // >= 8.18: add updatedBy, createdBy + { + set: { + field: 'slo.updatedBy', + value: slo.updatedBy, + ignore_failure: true, + }, + }, + { + set: { + field: 'slo.createdBy', + value: slo.createdBy, + ignore_failure: true, + }, + }, ], _meta: { description: `Ingest pipeline for SLO summary data [id: ${slo.id}, revision: ${slo.revision}]`, diff --git a/x-pack/solutions/observability/plugins/slo/server/assets/transform_templates/slo_transform_template.test.ts b/x-pack/solutions/observability/plugins/slo/server/assets/transform_templates/slo_transform_template.test.ts index d3c0a9ea67b5d..a8eeb411af238 100644 --- a/x-pack/solutions/observability/plugins/slo/server/assets/transform_templates/slo_transform_template.test.ts +++ b/x-pack/solutions/observability/plugins/slo/server/assets/transform_templates/slo_transform_template.test.ts @@ -143,7 +143,7 @@ describe('slo transform template', () => { }, defer_validation: true, _meta: { - version: 3.3, + version: 3.4, managed: true, managed_by: 'observability', }, @@ -247,7 +247,7 @@ describe('slo transform template', () => { }, defer_validation: true, _meta: { - version: 3.3, + version: 3.4, managed: true, managed_by: 'observability', }, diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/route.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/route.ts index b93076ace737f..cac23f8d1f1ef 100644 --- a/x-pack/solutions/observability/plugins/slo/server/routes/slo/route.ts +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/route.ts @@ -86,12 +86,13 @@ const createSLORoute = createSloServerRoute({ }, }, params: createSLOParamsSchema, - handler: async ({ context, response, params, logger, request, plugins, corePlugins }) => { + handler: async ({ context, params, logger, request, plugins, corePlugins }) => { await assertPlatinumLicense(plugins); const sloContext = await context.slo; const dataViews = await plugins.dataViews.start(); const core = await context.core; + const userId = core.security.authc.getCurrentUser()?.username!; const scopedClusterClient = core.elasticsearch.client; const esClient = core.elasticsearch.client.asCurrentUser; const soClient = core.savedObjects.client; @@ -127,7 +128,8 @@ const createSLORoute = createSloServerRoute({ summaryTransformManager, logger, spaceId, - basePath + basePath, + userId ); return await executeWithErrorHandler(() => createSLO.execute(params.body)); @@ -153,6 +155,7 @@ const inspectSLORoute = createSloServerRoute({ const core = await context.core; const scopedClusterClient = core.elasticsearch.client; const esClient = core.elasticsearch.client.asCurrentUser; + const username = core.security.authc.getCurrentUser()?.username!; const soClient = core.savedObjects.client; const repository = new KibanaSavedObjectsSLORepository(soClient, logger); const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); @@ -181,7 +184,8 @@ const inspectSLORoute = createSloServerRoute({ summaryTransformManager, logger, spaceId, - basePath + basePath, + username ); return await executeWithErrorHandler(() => createSLO.inspect(params.body)); @@ -208,6 +212,8 @@ const updateSLORoute = createSloServerRoute({ const core = await context.core; const scopedClusterClient = core.elasticsearch.client; const esClient = core.elasticsearch.client.asCurrentUser; + const userId = core.security.authc.getCurrentUser()?.username!; + const soClient = core.savedObjects.client; const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); const repository = new KibanaSavedObjectsSLORepository(soClient, logger); @@ -236,7 +242,8 @@ const updateSLORoute = createSloServerRoute({ scopedClusterClient, logger, spaceId, - basePath + basePath, + userId ); return await executeWithErrorHandler(() => updateSLO.execute(params.path.id, params.body)); @@ -320,8 +327,8 @@ const getSLORoute = createSloServerRoute({ const repository = new KibanaSavedObjectsSLORepository(soClient, logger); const burnRatesClient = new DefaultBurnRatesClient(esClient); const summaryClient = new DefaultSummaryClient(esClient, burnRatesClient); - const defintionClient = new SloDefinitionClient(repository, esClient, logger); - const getSLO = new GetSLO(defintionClient, summaryClient); + const definitionClient = new SloDefinitionClient(repository, esClient, logger); + const getSLO = new GetSLO(definitionClient, summaryClient); return await executeWithErrorHandler(() => getSLO.execute(params.path.id, spaceId, params.query) diff --git a/x-pack/solutions/observability/plugins/slo/server/services/__snapshots__/create_slo.test.ts.snap b/x-pack/solutions/observability/plugins/slo/server/services/__snapshots__/create_slo.test.ts.snap index 46acf96dde5c3..62ebd5242212e 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/__snapshots__/create_slo.test.ts.snap +++ b/x-pack/solutions/observability/plugins/slo/server/services/__snapshots__/create_slo.test.ts.snap @@ -7,7 +7,7 @@ Array [ "description": "Ingest pipeline for SLO rollup data", "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "description": "Ingest pipeline for SLO rollup data [id: unique-id, revision: 1]", "id": ".slo-observability.sli.pipeline-unique-id-1", @@ -45,7 +45,7 @@ Array [ ], "date_rounding": "M", "field": "@timestamp", - "index_name_prefix": ".slo-observability.sli-v3.3.", + "index_name_prefix": ".slo-observability.sli-v3.4.", }, }, Object { @@ -120,6 +120,7 @@ Array [ "slo": Object { "budgetingMethod": "occurrences", "createdAt": "2024-01-01T00:00:00.000Z", + "createdBy": "some-user-id", "description": "irrelevant", "groupBy": "*", "groupings": Object {}, @@ -148,6 +149,7 @@ Array [ "type": "rolling", }, "updatedAt": "2024-01-01T00:00:00.000Z", + "updatedBy": "some-user-id", }, "spaceId": "some-space", "status": "NO_DATA", @@ -160,7 +162,7 @@ Array [ }, }, "id": "slo-unique-id", - "index": ".slo-observability.summary-v3.3.temp", + "index": ".slo-observability.summary-v3.4.temp", "refresh": true, }, ] diff --git a/x-pack/solutions/observability/plugins/slo/server/services/__snapshots__/reset_slo.test.ts.snap b/x-pack/solutions/observability/plugins/slo/server/services/__snapshots__/reset_slo.test.ts.snap index ec81df9f08fdd..111db838f90dc 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/__snapshots__/reset_slo.test.ts.snap +++ b/x-pack/solutions/observability/plugins/slo/server/services/__snapshots__/reset_slo.test.ts.snap @@ -122,6 +122,7 @@ exports[`ResetSLO happy path resets all associated resources 6`] = ` Object { "budgetingMethod": "occurrences", "createdAt": 2023-01-01T00:00:00.000Z, + "createdBy": "irrelevant", "description": "irrelevant", "enabled": true, "groupBy": "*", @@ -165,6 +166,7 @@ exports[`ResetSLO happy path resets all associated resources 6`] = ` "type": "rolling", }, "updatedAt": 2023-01-01T00:00:00.000Z, + "updatedBy": "irrelevant", "version": 1, }, ], @@ -203,7 +205,7 @@ exports[`ResetSLO happy path resets all associated resources 8`] = ` "description": "Ingest pipeline for SLO rollup data", "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "description": "Ingest pipeline for SLO rollup data [id: irrelevant, revision: 1]", "id": ".slo-observability.sli.pipeline-irrelevant-1", @@ -241,7 +243,7 @@ exports[`ResetSLO happy path resets all associated resources 8`] = ` ], "date_rounding": "M", "field": "@timestamp", - "index_name_prefix": ".slo-observability.sli-v3.3.", + "index_name_prefix": ".slo-observability.sli-v3.4.", }, }, Object { @@ -275,7 +277,7 @@ exports[`ResetSLO happy path resets all associated resources 8`] = ` "description": "Ingest pipeline for SLO summary data [id: irrelevant, revision: 1]", "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "description": "Ingest pipeline for SLO summary data [id: irrelevant, revision: 1]", "id": ".slo-observability.summary.pipeline-irrelevant-1", @@ -525,6 +527,20 @@ exports[`ResetSLO happy path resets all associated resources 8`] = ` }", }, }, + Object { + "set": Object { + "field": "slo.updatedBy", + "ignore_failure": true, + "value": "irrelevant", + }, + }, + Object { + "set": Object { + "field": "slo.createdBy", + "ignore_failure": true, + "value": "irrelevant", + }, + }, ], }, ], @@ -549,6 +565,7 @@ exports[`ResetSLO happy path resets all associated resources 9`] = ` Object { "budgetingMethod": "occurrences", "createdAt": 2023-01-01T00:00:00.000Z, + "createdBy": "irrelevant", "description": "irrelevant", "enabled": true, "groupBy": "*", @@ -592,6 +609,7 @@ exports[`ResetSLO happy path resets all associated resources 9`] = ` "type": "rolling", }, "updatedAt": 2023-01-01T00:00:00.000Z, + "updatedBy": "irrelevant", "version": 1, }, ], @@ -668,6 +686,7 @@ exports[`ResetSLO happy path resets all associated resources 11`] = ` "slo": Object { "budgetingMethod": "occurrences", "createdAt": "2023-01-01T00:00:00.000Z", + "createdBy": "irrelevant", "description": "irrelevant", "groupBy": "*", "groupings": Object {}, @@ -700,6 +719,7 @@ exports[`ResetSLO happy path resets all associated resources 11`] = ` "type": "rolling", }, "updatedAt": "2023-01-01T00:00:00.000Z", + "updatedBy": "irrelevant", }, "spaceId": "some-space", "status": "NO_DATA", @@ -712,7 +732,7 @@ exports[`ResetSLO happy path resets all associated resources 11`] = ` }, }, "id": "slo-irrelevant", - "index": ".slo-observability.summary-v3.3.temp", + "index": ".slo-observability.summary-v3.4.temp", "refresh": true, }, ], diff --git a/x-pack/solutions/observability/plugins/slo/server/services/__snapshots__/slo_definition_client.test.ts.snap b/x-pack/solutions/observability/plugins/slo/server/services/__snapshots__/slo_definition_client.test.ts.snap index 671c5c13a39ea..0c521a2712b0e 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/__snapshots__/slo_definition_client.test.ts.snap +++ b/x-pack/solutions/observability/plugins/slo/server/services/__snapshots__/slo_definition_client.test.ts.snap @@ -9,6 +9,7 @@ Object { "slo": Object { "budgetingMethod": "occurrences", "createdAt": 2024-01-01T00:00:00.000Z, + "createdBy": "irrelevant", "description": "irrelevant", "enabled": true, "groupBy": "*", @@ -54,6 +55,7 @@ Object { "type": "rolling", }, "updatedAt": 2024-01-01T00:00:00.000Z, + "updatedBy": "irrelevant", "version": 1, }, } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.test.ts b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.test.ts index 342b1a4190748..e112bfbaf2d3d 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.test.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.test.ts @@ -51,7 +51,8 @@ describe('CreateSLO', () => { mockSummaryTransformManager, mockLogger, 'some-space', - httpServiceMock.createStartContract().basePath + httpServiceMock.createStartContract().basePath, + 'some-user-id' ); }); diff --git a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts index c74f49c1ccac8..8d596d2d27c44 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts @@ -40,7 +40,8 @@ export class CreateSLO { private summaryTransformManager: TransformManager, private logger: Logger, private spaceId: string, - private basePath: IBasePath + private basePath: IBasePath, + private username: string ) {} public async execute(params: CreateSLOParams): Promise { @@ -217,6 +218,8 @@ export class CreateSLO { tags: params.tags ?? [], createdAt: now, updatedAt: now, + createdBy: this.username, + updatedBy: this.username, groupBy: !!params.groupBy ? params.groupBy : ALL_VALUE, version: SLO_MODEL_VERSION, }; diff --git a/x-pack/solutions/observability/plugins/slo/server/services/find_slo.test.ts b/x-pack/solutions/observability/plugins/slo/server/services/find_slo.test.ts index b4e3656bb8e39..19fe4f27b6524 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/find_slo.test.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/find_slo.test.ts @@ -58,6 +58,8 @@ describe('FindSLO', () => { id: slo.id, name: 'irrelevant', description: 'irrelevant', + createdBy: 'irrelevant', + updatedBy: 'irrelevant', budgetingMethod: 'occurrences', indicator: { params: { diff --git a/x-pack/solutions/observability/plugins/slo/server/services/fixtures/slo.ts b/x-pack/solutions/observability/plugins/slo/server/services/fixtures/slo.ts index c290523512b9c..319221e5f2955 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/fixtures/slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/fixtures/slo.ts @@ -206,6 +206,8 @@ export const createSLO = (params: Partial = {}): SLODefinition => revision: 1, createdAt: now, updatedAt: now, + createdBy: 'irrelevant', + updatedBy: 'irrelevant', version: SLO_MODEL_VERSION, ...params, }); diff --git a/x-pack/solutions/observability/plugins/slo/server/services/get_slo.test.ts b/x-pack/solutions/observability/plugins/slo/server/services/get_slo.test.ts index a3665294ab5c2..59cca79cc842f 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/get_slo.test.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/get_slo.test.ts @@ -63,6 +63,8 @@ describe('GetSLO', () => { name: 'irrelevant', description: 'irrelevant', budgetingMethod: 'occurrences', + createdBy: 'irrelevant', + updatedBy: 'irrelevant', indicator: { params: { environment: 'irrelevant', diff --git a/x-pack/solutions/observability/plugins/slo/server/services/mocks/index.ts b/x-pack/solutions/observability/plugins/slo/server/services/mocks/index.ts index c6fa4a3d949f3..0b3c1d4d07453 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/mocks/index.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/mocks/index.ts @@ -26,6 +26,7 @@ const createTransformManagerMock = (): jest.Mocked => { start: jest.fn(), stop: jest.fn(), inspect: jest.fn(), + getVersion: jest.fn(), }; }; @@ -37,6 +38,7 @@ const createSummaryTransformManagerMock = (): jest.Mocked => { start: jest.fn(), stop: jest.fn(), inspect: jest.fn(), + getVersion: jest.fn(), }; }; diff --git a/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts b/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts index afbdb999fc064..01580bc92708b 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; +import { SavedObject, SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; import { Logger } from '@kbn/core/server'; import { ALL_VALUE, Paginated, Pagination, sloDefinitionSchema } from '@kbn/slo-schema'; import { isLeft } from 'fp-ts/lib/Either'; @@ -79,7 +79,7 @@ export class KibanaSavedObjectsSLORepository implements SLORepository { throw new SLONotFound(`SLO [${id}] not found`); } - const slo = this.toSLO(response.saved_objects[0].attributes); + const slo = this.toSLO(response.saved_objects[0]); if (slo === undefined) { throw new Error('Invalid stored SLO'); } @@ -116,7 +116,7 @@ export class KibanaSavedObjectsSLORepository implements SLORepository { }); return response.saved_objects - .map((slo) => this.toSLO(slo.attributes)) + .map((slo) => this.toSLO(slo)) .filter((slo) => slo !== undefined) as SLODefinition[]; } @@ -141,12 +141,13 @@ export class KibanaSavedObjectsSLORepository implements SLORepository { perPage: response.per_page, page: response.page, results: response.saved_objects - .map((savedObject) => this.toSLO(savedObject.attributes)) + .map((savedObject) => this.toSLO(savedObject)) .filter((slo) => slo !== undefined) as SLODefinition[], }; } - toSLO(storedSLO: StoredSLODefinition): SLODefinition | undefined { + toSLO(storedSLOObject: SavedObject): SLODefinition | undefined { + const storedSLO = storedSLOObject.attributes; const result = sloDefinitionSchema.decode({ ...storedSLO, // groupBy was added in 8.10.0 @@ -160,6 +161,8 @@ export class KibanaSavedObjectsSLORepository implements SLORepository { { preventInitialBackfill: false, syncDelay: '1m', frequency: '1m' }, storedSLO.settings ), + createdBy: storedSLO.createdBy ?? storedSLOObject.created_by, + updatedBy: storedSLO.updatedBy ?? storedSLOObject.updated_by, }); if (isLeft(result)) { diff --git a/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/__snapshots__/occurrences.test.ts.snap b/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/__snapshots__/occurrences.test.ts.snap index 114ae4de393fa..725c9df707040 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/__snapshots__/occurrences.test.ts.snap +++ b/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/__snapshots__/occurrences.test.ts.snap @@ -5,12 +5,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Summarise the rollup data of SLO: irrelevant [id: irrelevant, revision: 1].", "dest": Object { - "index": ".slo-observability.summary-v3.3", + "index": ".slo-observability.summary-v3.4", "pipeline": ".slo-observability.summary.pipeline-irrelevant-1", }, "frequency": "1m", @@ -212,7 +212,7 @@ Object { "unattended": true, }, "source": Object { - "index": ".slo-observability.sli-v3.3*", + "index": ".slo-observability.sli-v3.4*", "query": Object { "bool": Object { "filter": Array [ @@ -253,12 +253,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Summarise the rollup data of SLO: irrelevant [id: irrelevant, revision: 1].", "dest": Object { - "index": ".slo-observability.summary-v3.3", + "index": ".slo-observability.summary-v3.4", "pipeline": ".slo-observability.summary.pipeline-irrelevant-1", }, "frequency": "1m", @@ -460,7 +460,7 @@ Object { "unattended": true, }, "source": Object { - "index": ".slo-observability.sli-v3.3*", + "index": ".slo-observability.sli-v3.4*", "query": Object { "bool": Object { "filter": Array [ @@ -501,12 +501,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Summarise the rollup data of SLO: irrelevant [id: irrelevant, revision: 1].", "dest": Object { - "index": ".slo-observability.summary-v3.3", + "index": ".slo-observability.summary-v3.4", "pipeline": ".slo-observability.summary.pipeline-irrelevant-1", }, "frequency": "1m", @@ -708,7 +708,7 @@ Object { "unattended": true, }, "source": Object { - "index": ".slo-observability.sli-v3.3*", + "index": ".slo-observability.sli-v3.4*", "query": Object { "bool": Object { "filter": Array [ diff --git a/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/__snapshots__/timeslices_calendar_aligned.test.ts.snap b/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/__snapshots__/timeslices_calendar_aligned.test.ts.snap index ea635841aea6b..86f300e0bf217 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/__snapshots__/timeslices_calendar_aligned.test.ts.snap +++ b/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/__snapshots__/timeslices_calendar_aligned.test.ts.snap @@ -5,12 +5,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Summarise the rollup data of SLO: irrelevant [id: irrelevant, revision: 1].", "dest": Object { - "index": ".slo-observability.summary-v3.3", + "index": ".slo-observability.summary-v3.4", "pipeline": ".slo-observability.summary.pipeline-irrelevant-1", }, "frequency": "1m", @@ -236,7 +236,7 @@ Object { "unattended": true, }, "source": Object { - "index": ".slo-observability.sli-v3.3*", + "index": ".slo-observability.sli-v3.4*", "query": Object { "bool": Object { "filter": Array [ diff --git a/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/__snapshots__/timeslices_rolling.test.ts.snap b/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/__snapshots__/timeslices_rolling.test.ts.snap index d01bc36872fb5..e13acde32200b 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/__snapshots__/timeslices_rolling.test.ts.snap +++ b/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/__snapshots__/timeslices_rolling.test.ts.snap @@ -5,12 +5,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Summarise the rollup data of SLO: irrelevant [id: irrelevant, revision: 1].", "dest": Object { - "index": ".slo-observability.summary-v3.3", + "index": ".slo-observability.summary-v3.4", "pipeline": ".slo-observability.summary.pipeline-irrelevant-1", }, "frequency": "1m", @@ -212,7 +212,7 @@ Object { "unattended": true, }, "source": Object { - "index": ".slo-observability.sli-v3.3*", + "index": ".slo-observability.sli-v3.4*", "query": Object { "bool": Object { "filter": Array [ diff --git a/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/helpers/create_temp_summary.ts b/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/helpers/create_temp_summary.ts index c473ed184f40c..c717b8bd9ef76 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/helpers/create_temp_summary.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/helpers/create_temp_summary.ts @@ -31,7 +31,7 @@ export interface EsSummaryDocument { }; name: string | null; }; - // common fields + // SLO definition slo: { // >= 8.14: Add indicator.params on the temporary summary as well as real summary through summary pipeline indicator: { type: IndicatorTypes } | Indicator; @@ -48,6 +48,8 @@ export interface EsSummaryDocument { tags: string[]; createdAt?: string; // >= 8.14 updatedAt?: string; // >= 8.14 + createdBy?: string; // >= 8.18 + updatedBy?: string; // >= 8.18 }; goodEvents: number; totalEvents: number; @@ -132,6 +134,9 @@ export function createTempSummaryDocument( tags: slo.tags, createdAt: slo.createdAt.toISOString(), // added in 8.14, i.e. might be undefined updatedAt: slo.updatedAt.toISOString(), // added in 8.14, i.e. might be undefined + // Added in 8.18 + createdBy: slo.createdBy, + updatedBy: slo.updatedBy, }, goodEvents: 0, totalEvents: 0, diff --git a/x-pack/solutions/observability/plugins/slo/server/services/summay_transform_manager.ts b/x-pack/solutions/observability/plugins/slo/server/services/summay_transform_manager.ts index 9389210505b4c..139827b0425a3 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/summay_transform_manager.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/summay_transform_manager.ts @@ -111,4 +111,21 @@ export class DefaultSummaryTransformManager implements TransformManager { throw err; } } + + async getVersion(transformId: TransformId): Promise { + try { + const response = await retryTransientEsErrors( + () => + this.scopedClusterClient.asSecondaryAuthUser.transform.getTransform( + { transform_id: transformId }, + { ignore: [404] } + ), + { logger: this.logger } + ); + return response?.transforms[0]?._meta?.version; + } catch (err) { + this.logger.error(`Cannot retrieve SLO transform version [${transformId}]. ${err}`); + throw err; + } + } } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap index fe0c3a8904c05..cdc777ad666e1 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap @@ -360,12 +360,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.3", + "index": ".slo-observability.sli-v3.4", "pipeline": ".slo-observability.sli.pipeline-irrelevant-1", }, "frequency": "1m", @@ -508,12 +508,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.3", + "index": ".slo-observability.sli-v3.4", "pipeline": ".slo-observability.sli.pipeline-irrelevant-1", }, "frequency": "1m", @@ -656,12 +656,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.3", + "index": ".slo-observability.sli-v3.4", "pipeline": ".slo-observability.sli.pipeline-irrelevant-1", }, "frequency": "1m", diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap index a081c2829f2bc..b8c40bc80eafe 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap @@ -336,12 +336,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.3", + "index": ".slo-observability.sli-v3.4", "pipeline": ".slo-observability.sli.pipeline-irrelevant-1", }, "frequency": "1m", @@ -471,12 +471,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.3", + "index": ".slo-observability.sli-v3.4", "pipeline": ".slo-observability.sli.pipeline-irrelevant-1", }, "frequency": "1m", @@ -606,12 +606,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.3", + "index": ".slo-observability.sli-v3.4", "pipeline": ".slo-observability.sli.pipeline-irrelevant-1", }, "frequency": "1m", diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/histogram.test.ts.snap b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/histogram.test.ts.snap index 43026be44a3bb..b93bf06d5703f 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/histogram.test.ts.snap +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/histogram.test.ts.snap @@ -77,12 +77,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.3", + "index": ".slo-observability.sli-v3.4", "pipeline": ".slo-observability.sli.pipeline-irrelevant-1", }, "frequency": "1m", @@ -206,12 +206,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.3", + "index": ".slo-observability.sli-v3.4", "pipeline": ".slo-observability.sli.pipeline-irrelevant-1", }, "frequency": "1m", @@ -335,12 +335,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.3", + "index": ".slo-observability.sli-v3.4", "pipeline": ".slo-observability.sli.pipeline-irrelevant-1", }, "frequency": "1m", diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/kql_custom.test.ts.snap b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/kql_custom.test.ts.snap index 95e1e3abf6aa5..d3ec35b2ed40b 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/kql_custom.test.ts.snap +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/kql_custom.test.ts.snap @@ -118,12 +118,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.3", + "index": ".slo-observability.sli-v3.4", "pipeline": ".slo-observability.sli.pipeline-irrelevant-1", }, "frequency": "1m", @@ -220,12 +220,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.3", + "index": ".slo-observability.sli-v3.4", "pipeline": ".slo-observability.sli.pipeline-irrelevant-1", }, "frequency": "1m", @@ -322,12 +322,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.3", + "index": ".slo-observability.sli-v3.4", "pipeline": ".slo-observability.sli.pipeline-irrelevant-1", }, "frequency": "1m", diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/metric_custom.test.ts.snap b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/metric_custom.test.ts.snap index 4b7dab85cec60..1003fc0eb9e9a 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/metric_custom.test.ts.snap +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/metric_custom.test.ts.snap @@ -117,12 +117,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.3", + "index": ".slo-observability.sli-v3.4", "pipeline": ".slo-observability.sli.pipeline-irrelevant-1", }, "frequency": "1m", @@ -257,12 +257,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.3", + "index": ".slo-observability.sli-v3.4", "pipeline": ".slo-observability.sli.pipeline-irrelevant-1", }, "frequency": "1m", diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/synthetics_availability.test.ts.snap b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/synthetics_availability.test.ts.snap index 309fdc7ffffb3..68d20e9f68545 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/synthetics_availability.test.ts.snap +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/synthetics_availability.test.ts.snap @@ -5,12 +5,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.3", + "index": ".slo-observability.sli-v3.4", "pipeline": ".slo-observability.sli.pipeline-irrelevant-1", }, "frequency": "1m", diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/timeslice_metric.test.ts.snap b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/timeslice_metric.test.ts.snap index 449d1c2fb74d2..78988adf8be44 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/timeslice_metric.test.ts.snap +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/__snapshots__/timeslice_metric.test.ts.snap @@ -33,12 +33,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.3", + "index": ".slo-observability.sli-v3.4", "pipeline": ".slo-observability.sli.pipeline-irrelevant-1", }, "frequency": "1m", @@ -224,12 +224,12 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.3, + "version": 3.4, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.3", + "index": ".slo-observability.sli-v3.4", "pipeline": ".slo-observability.sli.pipeline-irrelevant-1", }, "frequency": "1m", diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_manager.ts b/x-pack/solutions/observability/plugins/slo/server/services/transform_manager.ts index c07c8d78a5ca4..e95b04ca6b7da 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_manager.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_manager.ts @@ -21,6 +21,7 @@ export interface TransformManager { start(transformId: TransformId): Promise; stop(transformId: TransformId): Promise; uninstall(transformId: TransformId): Promise; + getVersion(transformId: TransformId): Promise; } export class DefaultTransformManager implements TransformManager { @@ -133,6 +134,23 @@ export class DefaultTransformManager implements TransformManager { } } + async getVersion(transformId: TransformId): Promise { + try { + const response = await retryTransientEsErrors( + () => + this.scopedClusterClient.asSecondaryAuthUser.transform.getTransform( + { transform_id: transformId }, + { ignore: [404] } + ), + { logger: this.logger } + ); + return response?.transforms[0]?._meta?.version; + } catch (err) { + this.logger.error(`Cannot retrieve SLO transform version [${transformId}]. ${err}`); + throw err; + } + } + async scheduleNowTransform(transformId: TransformId) { this.scopedClusterClient.asSecondaryAuthUser.transform .scheduleNowTransform({ transform_id: transformId }) diff --git a/x-pack/solutions/observability/plugins/slo/server/services/unsafe_federated/__snapshots__/remote_summary_doc_to_slo.test.ts.snap b/x-pack/solutions/observability/plugins/slo/server/services/unsafe_federated/__snapshots__/remote_summary_doc_to_slo.test.ts.snap index 4825ed65e4fc9..e281e80422704 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/unsafe_federated/__snapshots__/remote_summary_doc_to_slo.test.ts.snap +++ b/x-pack/solutions/observability/plugins/slo/server/services/unsafe_federated/__snapshots__/remote_summary_doc_to_slo.test.ts.snap @@ -4,6 +4,7 @@ exports[`FromRemoteSummaryDocToSlo with kibana < v8.14 fallbacks to dummy indica Object { "budgetingMethod": "timeslices", "createdAt": 2024-01-01T00:00:00.000Z, + "createdBy": undefined, "description": "irrelevant", "enabled": true, "groupBy": "*", @@ -49,6 +50,7 @@ Object { "type": "rolling", }, "updatedAt": 2024-01-01T00:00:00.000Z, + "updatedBy": undefined, "version": 1, } `; @@ -57,6 +59,7 @@ exports[`FromRemoteSummaryDocToSlo with kibana >= v8.14 uses the stringified ind Object { "budgetingMethod": "occurrences", "createdAt": 2024-02-01T00:00:00.000Z, + "createdBy": undefined, "description": "irrelevant", "enabled": true, "groupBy": "*", @@ -99,6 +102,59 @@ Object { "type": "rolling", }, "updatedAt": 2024-02-01T00:00:00.000Z, + "updatedBy": undefined, + "version": 1, +} +`; + +exports[`FromRemoteSummaryDocToSlo with kibana >= v8.18 uses the provided updatedBy and createdBy 1`] = ` +Object { + "budgetingMethod": "occurrences", + "createdAt": 2024-02-01T00:00:00.000Z, + "createdBy": "john", + "description": "irrelevant", + "enabled": true, + "groupBy": "*", + "id": "irrelevant", + "indicator": Object { + "params": Object { + "good": "irrelevant", + "index": "irrelvant", + "timestampField": "irrelevant", + "total": "irrelevant", + }, + "type": "sli.kql.custom", + }, + "name": "irrelevant", + "objective": Object { + "target": 0.9999, + "timesliceTarget": undefined, + "timesliceWindow": undefined, + }, + "revision": 1, + "settings": Object { + "frequency": Duration { + "unit": "m", + "value": 1, + }, + "preventInitialBackfill": false, + "syncDelay": Duration { + "unit": "m", + "value": 1, + }, + }, + "tags": Array [ + "prod", + ], + "timeWindow": Object { + "duration": Duration { + "unit": "d", + "value": 7, + }, + "type": "rolling", + }, + "updatedAt": 2024-02-01T00:00:00.000Z, + "updatedBy": "jane", "version": 1, } `; diff --git a/x-pack/solutions/observability/plugins/slo/server/services/unsafe_federated/remote_summary_doc_to_slo.test.ts b/x-pack/solutions/observability/plugins/slo/server/services/unsafe_federated/remote_summary_doc_to_slo.test.ts index be91f8b694753..486b93d3de08b 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/unsafe_federated/remote_summary_doc_to_slo.test.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/unsafe_federated/remote_summary_doc_to_slo.test.ts @@ -154,4 +154,79 @@ describe('FromRemoteSummaryDocToSlo', () => { expect(slo).toMatchSnapshot(); }); }); + + describe('with kibana >= v8.18', () => { + it('uses the provided updatedBy and createdBy', () => { + const slo = fromRemoteSummaryDocumentToSloDefinition( + { + service: { + environment: null, + name: null, + }, + transaction: { + name: null, + type: null, + }, + monitor: { + name: null, + config_id: null, + }, + observer: { + name: null, + geo: { + name: null, + }, + }, + slo: { + indicator: { + type: 'sli.kql.custom', + params: { + index: 'irrelvant', + good: 'irrelevant', + total: 'irrelevant', + timestampField: 'irrelevant', + }, // added in 8.14 + }, + timeWindow: { + duration: '7d', + type: 'rolling', + }, + groupBy: ALL_VALUE, + groupings: {}, + instanceId: ALL_VALUE, + name: 'irrelevant', + description: 'irrelevant', + id: 'irrelevant', + budgetingMethod: 'occurrences', + revision: 1, + objective: { + target: 0.9999, + }, + tags: ['prod'], + createdAt: '2024-02-01T00:00:00.000Z', // added in 8.14 + updatedAt: '2024-02-01T00:00:00.000Z', // added in 8.14 + createdBy: 'john', + updatedBy: 'jane', + }, + goodEvents: 0, + totalEvents: 0, + errorBudgetEstimated: false, + errorBudgetRemaining: 1, + errorBudgetConsumed: 0, + errorBudgetInitial: 1 - 0.9999, + sliValue: -1, + statusCode: 0, + status: 'NO_DATA', + isTempDoc: true, + spaceId: 'irrelevant', + kibanaUrl: 'http://kibana.com/base-path', // added in 8.14 + summaryUpdatedAt: null, + latestSliTimestamp: null, + }, + loggerMock + ); + + expect(slo).toMatchSnapshot(); + }); + }); }); diff --git a/x-pack/solutions/observability/plugins/slo/server/services/unsafe_federated/remote_summary_doc_to_slo.ts b/x-pack/solutions/observability/plugins/slo/server/services/unsafe_federated/remote_summary_doc_to_slo.ts index 0d98a021f505f..1efe9f58c3bdd 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/unsafe_federated/remote_summary_doc_to_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/unsafe_federated/remote_summary_doc_to_slo.ts @@ -42,6 +42,8 @@ export function fromRemoteSummaryDocumentToSloDefinition( updatedAt: summaryDoc.slo.updatedAt ?? '2024-01-01T00:00:00.000Z', // fallback prior 8.14 groupBy: summaryDoc.slo.groupBy, version: 1, + createdBy: summaryDoc.slo.createdBy, + updatedBy: summaryDoc.slo.updatedBy, }); if (isLeft(res)) { diff --git a/x-pack/solutions/observability/plugins/slo/server/services/update_slo.test.ts b/x-pack/solutions/observability/plugins/slo/server/services/update_slo.test.ts index 9417e4779a5e2..81084683d7978 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/update_slo.test.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/update_slo.test.ts @@ -21,6 +21,7 @@ import { getSLOSummaryTransformId, getSLOTransformId, SLO_DESTINATION_INDEX_PATTERN, + SLO_RESOURCES_VERSION, SLO_SUMMARY_DESTINATION_INDEX_PATTERN, } from '../../common/constants'; import { SLODefinition } from '../domain/models'; @@ -64,11 +65,12 @@ describe('UpdateSLO', () => { mockScopedClusterClient, mockLogger, 'some-space', - httpServiceMock.createStartContract().basePath + httpServiceMock.createStartContract().basePath, + 'some-user-id' ); }); - describe('when the update payload does not change the original SLO', () => { + describe('when the update does not change the original SLO', () => { function expectNoCallsToAnyMocks() { expect(mockEsClient.security.hasPrivileges).not.toBeCalled(); @@ -86,6 +88,10 @@ describe('UpdateSLO', () => { expect(mockScopedClusterClient.asSecondaryAuthUser.ingest.putPipeline).not.toBeCalled(); } + beforeEach(() => { + mockSummaryTransformManager.getVersion.mockResolvedValue(SLO_RESOURCES_VERSION); + }); + it('returns early with a fully identical SLO payload', async () => { const slo = createSLO(); mockRepository.findById.mockResolvedValueOnce(slo); @@ -194,14 +200,71 @@ describe('UpdateSLO', () => { }); }); - describe('handles breaking changes', () => { + describe('without breaking changes update', () => { beforeEach(() => { mockEsClient.security.hasPrivileges.mockResolvedValue({ has_all_requested: true, } as SecurityHasPrivilegesResponse); }); - it('consideres a settings change as a breaking change', async () => { + describe('when resources are up-to-date', () => { + beforeEach(() => { + mockSummaryTransformManager.getVersion.mockResolvedValue(SLO_RESOURCES_VERSION); + }); + it('updates the summary pipeline with the new non-breaking changes', async () => { + const slo = createSLO(); + mockRepository.findById.mockResolvedValueOnce(slo); + await updateSLO.execute(slo.id, { name: 'updated name' }); + + expectNonBreakingChangeUpdatedResources(); + }); + + function expectNonBreakingChangeUpdatedResources() { + expect(mockScopedClusterClient.asSecondaryAuthUser.ingest.putPipeline).toHaveBeenCalled(); + + expect(mockTransformManager.install).not.toHaveBeenCalled(); + expect(mockTransformManager.start).not.toHaveBeenCalled(); + expect(mockSummaryTransformManager.install).not.toHaveBeenCalled(); + expect(mockSummaryTransformManager.start).not.toHaveBeenCalled(); + + expect(mockEsClient.index).not.toHaveBeenCalled(); + } + }); + + describe('when resources are running on an older version', () => { + beforeEach(() => { + mockSummaryTransformManager.getVersion.mockResolvedValue(SLO_RESOURCES_VERSION - 2); + }); + + it('consideres the non-breaking changes as breaking', async () => { + const slo = createSLO(); + mockRepository.findById.mockResolvedValueOnce(slo); + await updateSLO.execute(slo.id, { name: 'updated name' }); + + expect(mockRepository.update).toHaveBeenCalledWith( + expect.objectContaining({ + ...slo, + name: 'updated name', + revision: 2, + updatedAt: expect.anything(), + updatedBy: 'some-user-id', + }) + ); + expectInstallationOfUpdatedSLOResources(); + expectDeletionOfOriginalSLOResources(slo); + }); + }); + }); + + describe('with breaking changes update', () => { + beforeEach(() => { + mockEsClient.security.hasPrivileges.mockResolvedValue({ + has_all_requested: true, + } as SecurityHasPrivilegesResponse); + mockSummaryTransformManager.getVersion.mockResolvedValue(SLO_RESOURCES_VERSION); + }); + + it('considers a settings change as a breaking change', async () => { const slo = createSLO(); mockRepository.findById.mockResolvedValueOnce(slo); @@ -214,17 +277,12 @@ describe('UpdateSLO', () => { expectDeletionOfOriginalSLOResources(slo); expect(mockRepository.update).toHaveBeenCalledWith( - expect.objectContaining({ - ...slo, - settings: newSettings, - revision: 2, - updatedAt: expect.anything(), - }) + expect.objectContaining({ settings: newSettings, revision: 2 }) ); expectInstallationOfUpdatedSLOResources(); }); - it('consideres a budgeting method change as a breaking change', async () => { + it('considers a budgeting method change as a breaking change', async () => { const slo = createSLO({ budgetingMethod: 'occurrences' }); mockRepository.findById.mockResolvedValueOnce(slo); @@ -241,7 +299,7 @@ describe('UpdateSLO', () => { expectDeletionOfOriginalSLOResources(slo); }); - it('consideres a timeWindow change as a breaking change', async () => { + it('considers a timeWindow change as a breaking change', async () => { const slo = createSLOWithTimeslicesBudgetingMethod(); mockRepository.findById.mockResolvedValueOnce(slo); @@ -253,7 +311,7 @@ describe('UpdateSLO', () => { expectDeletionOfOriginalSLOResources(slo); }); - it('consideres a timeslice target change as a breaking change', async () => { + it('considers a timeslice target change as a breaking change', async () => { const slo = createSLOWithTimeslicesBudgetingMethod(); mockRepository.findById.mockResolvedValueOnce(slo); @@ -269,7 +327,7 @@ describe('UpdateSLO', () => { expectDeletionOfOriginalSLOResources(slo); }); - it('consideres a timeslice window change as a breaking change', async () => { + it('considers a timeslice window change as a breaking change', async () => { const slo = createSLOWithTimeslicesBudgetingMethod(); mockRepository.findById.mockResolvedValueOnce(slo); @@ -285,7 +343,7 @@ describe('UpdateSLO', () => { expectDeletionOfOriginalSLOResources(slo); }); - it('consideres an indicator change as a breaking change', async () => { + it('considers an indicator change as a breaking change', async () => { const slo = createSLOWithTimeslicesBudgetingMethod(); mockRepository.findById.mockResolvedValueOnce(slo); @@ -297,7 +355,7 @@ describe('UpdateSLO', () => { expectDeletionOfOriginalSLOResources(slo); }); - it('consideres a groupBy change as a breaking change', async () => { + it('considers a groupBy change as a breaking change', async () => { const slo = createSLOWithTimeslicesBudgetingMethod(); mockRepository.findById.mockResolvedValueOnce(slo); @@ -315,6 +373,7 @@ describe('UpdateSLO', () => { mockEsClient.security.hasPrivileges.mockResolvedValue({ has_all_requested: true, } as SecurityHasPrivilegesResponse); + mockSummaryTransformManager.getVersion.mockResolvedValue(SLO_RESOURCES_VERSION); }); it('throws a SecurityException error when the user does not have the required privileges on the source index', async () => { @@ -388,6 +447,30 @@ describe('UpdateSLO', () => { }); }); + describe('Update also updates updatedBy field', () => { + beforeEach(() => { + mockEsClient.security.hasPrivileges.mockResolvedValue({ + has_all_requested: true, + } as SecurityHasPrivilegesResponse); + }); + + it('updates the updatedBy field with the user id', async () => { + const originalSlo = createSLO({ + id: 'original-id', + indicator: createAPMTransactionErrorRateIndicator({ environment: 'development' }), + }); + mockRepository.findById.mockResolvedValueOnce(originalSlo); + + const newIndicator = createAPMTransactionErrorRateIndicator({ environment: 'production' }); + + await updateSLO.execute(originalSlo.id, { indicator: newIndicator }); + + expect(mockRepository.update).toHaveBeenCalledWith( + expect.objectContaining({ updatedBy: 'some-user-id' }) + ); + }); + }); + function expectInstallationOfUpdatedSLOResources() { expect(mockTransformManager.install).toHaveBeenCalled(); expect(mockTransformManager.start).toHaveBeenCalled(); diff --git a/x-pack/solutions/observability/plugins/slo/server/services/update_slo.ts b/x-pack/solutions/observability/plugins/slo/server/services/update_slo.ts index 30d62140f80d9..05f518f0946a9 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/update_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/update_slo.ts @@ -11,6 +11,7 @@ import { asyncForEach } from '@kbn/std'; import { isEqual, pick } from 'lodash'; import { SLO_DESTINATION_INDEX_PATTERN, + SLO_RESOURCES_VERSION, SLO_SUMMARY_DESTINATION_INDEX_PATTERN, SLO_SUMMARY_TEMP_INDEX_NAME, getSLOPipelineId, @@ -38,7 +39,8 @@ export class UpdateSLO { private scopedClusterClient: IScopedClusterClient, private logger: Logger, private spaceId: string, - private basePath: IBasePath + private basePath: IBasePath, + private userId: string ) {} public async execute(sloId: string, params: UpdateSLOParams): Promise { @@ -53,18 +55,11 @@ export class UpdateSLO { return this.toResponse(originalSlo); } - const fields = [ - 'indicator', - 'groupBy', - 'timeWindow', - 'objective', - 'budgetingMethod', - 'settings', - ]; - const requireRevisionBump = !isEqual(pick(originalSlo, fields), pick(updatedSlo, fields)); + const requireRevisionBump = await this.isRevisionBumpRequired(originalSlo, updatedSlo); updatedSlo = Object.assign(updatedSlo, { updatedAt: new Date(), + updatedBy: this.userId, revision: requireRevisionBump ? originalSlo.revision + 1 : originalSlo.revision, }); @@ -77,23 +72,8 @@ export class UpdateSLO { rollbackOperations.push(() => this.repository.update(originalSlo)); if (!requireRevisionBump) { - // At this point, we still need to update the sli and summary pipeline to include the changes (id and revision in the rollup index) and (name, desc, tags, ...) in the summary index - + // we only have to update the summary pipeline to include the non-breaking changes (name, desc, tags, ...) in the summary index try { - await retryTransientEsErrors( - () => - this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( - getSLOPipelineTemplate(updatedSlo) - ), - { logger: this.logger } - ); - rollbackOperations.push(() => - this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( - { id: getSLOPipelineId(updatedSlo.id, updatedSlo.revision) }, - { ignore: [404] } - ) - ); - await retryTransientEsErrors( () => this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( @@ -205,6 +185,26 @@ export class UpdateSLO { return this.toResponse(updatedSlo); } + private async isRevisionBumpRequired(originalSlo: SLODefinition, updatedSlo: SLODefinition) { + const fields = [ + 'indicator', + 'groupBy', + 'timeWindow', + 'objective', + 'budgetingMethod', + 'settings', + ]; + const hasBreakingChanges = !isEqual(pick(originalSlo, fields), pick(updatedSlo, fields)); + const currentResourcesVersion = await this.summaryTransformManager.getVersion( + getSLOSummaryTransformId(originalSlo.id, originalSlo.revision) + ); + + const hasOutdatedVersion = + currentResourcesVersion === undefined || currentResourcesVersion < SLO_RESOURCES_VERSION; + + return hasBreakingChanges || hasOutdatedVersion; + } + private async deleteOriginalSLO(originalSlo: SLODefinition) { try { const originalRollupTransformId = getSLOTransformId(originalSlo.id, originalSlo.revision); diff --git a/x-pack/solutions/observability/plugins/slo/server/types.ts b/x-pack/solutions/observability/plugins/slo/server/types.ts index 5ec6e2c51e902..db4e44305c86c 100644 --- a/x-pack/solutions/observability/plugins/slo/server/types.ts +++ b/x-pack/solutions/observability/plugins/slo/server/types.ts @@ -21,6 +21,7 @@ import { TaskManagerStartContract, } from '@kbn/task-manager-plugin/server'; import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; +import { SecurityPluginStart } from '@kbn/security-plugin/server'; import type { KibanaRequest } from '@kbn/core/server'; import type { SloClient } from './client'; @@ -44,6 +45,7 @@ export interface SLOPluginSetupDependencies { usageCollection: UsageCollectionSetup; licensing: LicensingPluginSetup; dataViews: DataViewsServerPluginStart; + security: SecurityPluginStart; } export interface SLOPluginStartDependencies { diff --git a/x-pack/solutions/observability/plugins/slo/tsconfig.json b/x-pack/solutions/observability/plugins/slo/tsconfig.json index f5da461434f32..aadc799332377 100644 --- a/x-pack/solutions/observability/plugins/slo/tsconfig.json +++ b/x-pack/solutions/observability/plugins/slo/tsconfig.json @@ -102,5 +102,6 @@ "@kbn/server-route-repository-client", "@kbn/security-plugin-types-public", "@kbn/core-test-helpers-kbn-server", + "@kbn/security-plugin", ] } diff --git a/x-pack/solutions/observability/plugins/streams/server/lib/streams/client.ts b/x-pack/solutions/observability/plugins/streams/server/lib/streams/client.ts index a4ab3823d41da..83fa13bc5f066 100644 --- a/x-pack/solutions/observability/plugins/streams/server/lib/streams/client.ts +++ b/x-pack/solutions/observability/plugins/streams/server/lib/streams/client.ts @@ -81,6 +81,7 @@ export class StreamsClient { assetClient: AssetClient; storageClient: StreamsStorageClient; logger: Logger; + isServerless: boolean; } ) {} @@ -178,6 +179,7 @@ export class StreamsClient { definition, logger, scopedClusterClient, + isServerless: this.dependencies.isServerless, }); } else if (isIngestStream(definition)) { await syncIngestStreamDefinitionObjects({ diff --git a/x-pack/solutions/observability/plugins/streams/server/lib/streams/errors/detected_mapping_failure.ts b/x-pack/solutions/observability/plugins/streams/server/lib/streams/errors/detected_mapping_failure.ts new file mode 100644 index 0000000000000..b026b150b64e8 --- /dev/null +++ b/x-pack/solutions/observability/plugins/streams/server/lib/streams/errors/detected_mapping_failure.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. + */ + +export class DetectedMappingFailure extends Error { + constructor(message: string) { + super(message); + this.name = 'DetectedMappingFailure'; + } +} diff --git a/x-pack/solutions/observability/plugins/streams/server/lib/streams/helpers/sync.ts b/x-pack/solutions/observability/plugins/streams/server/lib/streams/helpers/sync.ts index 140b32449b068..d91cac1ddc3cc 100644 --- a/x-pack/solutions/observability/plugins/streams/server/lib/streams/helpers/sync.ts +++ b/x-pack/solutions/observability/plugins/streams/server/lib/streams/helpers/sync.ts @@ -44,8 +44,10 @@ export async function syncWiredStreamDefinitionObjects({ definition, scopedClusterClient, logger, + isServerless, }: SyncStreamParamsBase & { definition: WiredStreamDefinition; + isServerless: boolean; }) { const componentTemplate = generateLayer(definition.name, definition); await upsertComponent({ @@ -72,7 +74,7 @@ export async function syncWiredStreamDefinitionObjects({ await upsertTemplate({ esClient: scopedClusterClient.asCurrentUser, logger, - template: generateIndexTemplate(definition.name), + template: generateIndexTemplate(definition.name, isServerless), }); await upsertDataStream({ diff --git a/x-pack/solutions/observability/plugins/streams/server/lib/streams/index_templates/generate_index_template.ts b/x-pack/solutions/observability/plugins/streams/server/lib/streams/index_templates/generate_index_template.ts index 0134951c8079a..ec4aa4464eeac 100644 --- a/x-pack/solutions/observability/plugins/streams/server/lib/streams/index_templates/generate_index_template.ts +++ b/x-pack/solutions/observability/plugins/streams/server/lib/streams/index_templates/generate_index_template.ts @@ -9,7 +9,7 @@ import { ASSET_VERSION } from '../../../../common/constants'; import { getProcessingPipelineName } from '../ingest_pipelines/name'; import { getIndexTemplateName } from './name'; -export function generateIndexTemplate(id: string) { +export function generateIndexTemplate(id: string, isServerless: boolean) { const composedOf = id.split('.').reduce((acc, _, index, array) => { const parent = array.slice(0, index + 1).join('.'); return [...acc, `${parent}@stream.layer`]; @@ -27,7 +27,7 @@ export function generateIndexTemplate(id: string) { }, data_stream: { hidden: false, - failure_store: true, + failure_store: isServerless ? undefined : true, // TODO: Enable failure store for serverless once it is rolled out }, template: { settings: { diff --git a/x-pack/solutions/observability/plugins/streams/server/lib/streams/service.ts b/x-pack/solutions/observability/plugins/streams/server/lib/streams/service.ts index 2b4d710c6886c..f66b1e16b6fe8 100644 --- a/x-pack/solutions/observability/plugins/streams/server/lib/streams/service.ts +++ b/x-pack/solutions/observability/plugins/streams/server/lib/streams/service.ts @@ -52,6 +52,8 @@ export class StreamsService { const scopedClusterClient = coreStart.elasticsearch.client.asScoped(request); + const isServerless = coreStart.elasticsearch.getCapabilities().serverless; + const storageAdapter = new StorageIndexAdapter( scopedClusterClient.asInternalUser, logger, @@ -63,6 +65,7 @@ export class StreamsService { logger, scopedClusterClient, storageClient: storageAdapter.getClient(), + isServerless, }); } } diff --git a/x-pack/solutions/observability/plugins/streams/server/routes/streams/management/route.ts b/x-pack/solutions/observability/plugins/streams/server/routes/streams/management/route.ts index cc3ce94536261..a6f2ae8a29911 100644 --- a/x-pack/solutions/observability/plugins/streams/server/routes/streams/management/route.ts +++ b/x-pack/solutions/observability/plugins/streams/server/routes/streams/management/route.ts @@ -135,7 +135,7 @@ export const sampleStreamRoute = createServerRoute({ condition: z.optional(conditionSchema), start: z.optional(z.number()), end: z.optional(z.number()), - number: z.optional(z.number()), + size: z.optional(z.number()), }), }), handler: async ({ params, request, getScopedClients }): Promise<{ documents: unknown[] }> => { @@ -146,18 +146,20 @@ export const sampleStreamRoute = createServerRoute({ if (!read) { throw new DefinitionNotFound(`Stream definition for ${params.path.id} not found.`); } + + const { condition, start, end, size } = params.body; const searchBody = { query: { bool: { must: [ - isCompleteCondition(params.body.condition) - ? conditionToQueryDsl(params.body.condition) + Boolean(condition && isCompleteCondition(condition)) + ? conditionToQueryDsl(condition) : { match_all: {} }, { range: { '@timestamp': { - gte: params.body.start, - lte: params.body.end, + gte: start, + lte: end, format: 'epoch_millis', }, }, @@ -170,12 +172,14 @@ export const sampleStreamRoute = createServerRoute({ // ingest in the painless condition checks. // This is less efficient than it could be - in some cases, these fields _are_ indexed with the right type and we could use them directly. // This can be optimized in the future. - runtime_mappings: Object.fromEntries( - getFields(params.body.condition).map((field) => [ - field.name, - { type: field.type === 'string' ? 'keyword' : 'double' }, - ]) - ), + runtime_mappings: condition + ? Object.fromEntries( + getFields(condition).map((field) => [ + field.name, + { type: field.type === 'string' ? 'keyword' : 'double' }, + ]) + ) + : undefined, sort: [ { '@timestamp': { @@ -183,7 +187,9 @@ export const sampleStreamRoute = createServerRoute({ }, }, ], - size: params.body.number, + terminate_after: size, + track_total_hits: false, + size, }; const results = await scopedClusterClient.asCurrentUser.search({ index: params.path.id, diff --git a/x-pack/solutions/observability/plugins/streams/server/routes/streams/processing/route.ts b/x-pack/solutions/observability/plugins/streams/server/routes/streams/processing/route.ts index 897c6f02ec804..af65843ff4aac 100644 --- a/x-pack/solutions/observability/plugins/streams/server/routes/streams/processing/route.ts +++ b/x-pack/solutions/observability/plugins/streams/server/routes/streams/processing/route.ts @@ -5,15 +5,19 @@ * 2.0. */ +/* eslint-disable @typescript-eslint/naming-convention */ + import { z } from '@kbn/zod'; import { notFound, internal, badRequest } from '@hapi/boom'; -import { FieldDefinitionConfig, processingDefinitionSchema } from '@kbn/streams-schema'; -import { calculateObjectDiff, flattenObject } from '@kbn/object-utils'; import { - IngestSimulateResponse, - IngestSimulateSimulateDocumentResult, -} from '@elastic/elasticsearch/lib/api/types'; + FieldDefinitionConfig, + fieldDefinitionConfigSchema, + processingDefinitionSchema, +} from '@kbn/streams-schema'; +import { calculateObjectDiff, flattenObject } from '@kbn/object-utils'; import { isEmpty } from 'lodash'; +import { IScopedClusterClient } from '@kbn/core/server'; +import { DetectedMappingFailure } from '../../../lib/streams/errors/detected_mapping_failure'; import { NonAdditiveProcessor } from '../../../lib/streams/errors/non_additive_processor'; import { SimulationFailed } from '../../../lib/streams/errors/simulation_failed'; import { formatToIngestProcessors } from '../../../lib/streams/helpers/processing'; @@ -21,6 +25,17 @@ import { createServerRoute } from '../../create_server_route'; import { DefinitionNotFound } from '../../../lib/streams/errors'; import { checkAccess } from '../../../lib/streams/stream_crud'; +const paramsSchema = z.object({ + path: z.object({ id: z.string() }), + body: z.object({ + processing: z.array(processingDefinitionSchema), + documents: z.array(z.record(z.unknown())), + detected_fields: z.array(fieldDefinitionConfigSchema.extend({ name: z.string() })).optional(), + }), +}); + +type ProcessingSimulateParams = z.infer; + export const simulateProcessorRoute = createServerRoute({ endpoint: 'POST /api/streams/{id}/processing/_simulate', options: { @@ -33,82 +48,153 @@ export const simulateProcessorRoute = createServerRoute({ 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', }, }, - params: z.object({ - path: z.object({ id: z.string() }), - body: z.object({ - processing: z.array(processingDefinitionSchema), - documents: z.array(z.record(z.unknown())), - }), - }), - handler: async ({ params, request, response, getScopedClients }) => { + params: paramsSchema, + handler: async ({ params, request, getScopedClients }) => { try { const { scopedClusterClient } = await getScopedClients({ request }); - const hasAccess = await checkAccess({ id: params.path.id, scopedClusterClient }); - if (!hasAccess) { + const { read } = await checkAccess({ id: params.path.id, scopedClusterClient }); + if (!read) { throw new DefinitionNotFound(`Stream definition for ${params.path.id} not found.`); } - // Normalize processing definition to pipeline processors - const processors = formatToIngestProcessors(params.body.processing); - // Convert input documents to ingest simulation format - const docs = params.body.documents.map((doc) => ({ _source: doc })); - - let simulationResult: IngestSimulateResponse; - try { - simulationResult = await scopedClusterClient.asCurrentUser.ingest.simulate({ - verbose: true, - pipeline: { processors }, - docs, - }); - } catch (error) { - throw new SimulationFailed(error); - } - const simulationDiffs = computeSimulationDiffs(simulationResult, docs); + const simulationBody = prepareSimulationBody(params); - const updatedFields = computeUpdatedFields(simulationDiffs); - if (!isEmpty(updatedFields)) { - throw new NonAdditiveProcessor( - `The processor is not additive to the documents. It might update fields [${updatedFields.join()}]` - ); - } + const simulationResult = await executeSimulation(scopedClusterClient, simulationBody); - const documents = computeSimulationDocuments(simulationResult, docs); - const detectedFields = computeDetectedFields(simulationDiffs); - const successRate = computeSuccessRate(simulationResult); - const failureRate = 1 - successRate; + const simulationDiffs = prepareSimulationDiffs(simulationResult, simulationBody.docs); - return { - documents, - success_rate: parseFloat(successRate.toFixed(2)), - failure_rate: parseFloat(failureRate.toFixed(2)), - detected_fields: detectedFields, - }; + assertSimulationResult(simulationResult, simulationDiffs); + + return prepareSimulationResponse( + simulationResult, + simulationBody.docs, + simulationDiffs, + params.body.detected_fields + ); } catch (error) { if (error instanceof DefinitionNotFound) { throw notFound(error); } - - if (error instanceof SimulationFailed || error instanceof NonAdditiveProcessor) { + if ( + error instanceof SimulationFailed || + error instanceof NonAdditiveProcessor || + error instanceof DetectedMappingFailure + ) { throw badRequest(error); } - throw internal(error); } }, }); -const computeSimulationDiffs = ( - simulation: IngestSimulateResponse, +const prepareSimulationBody = (params: ProcessingSimulateParams) => { + const { path, body } = params; + const { processing, documents, detected_fields } = body; + + const processors = formatToIngestProcessors(processing); + const docs = documents.map((doc, id) => ({ + _index: path.id, + _id: id.toString(), + _source: doc, + })); + + const simulationBody: any = { + docs, + pipeline_substitutions: { + [`${path.id}@stream.processing`]: { + processors, + }, + }, + }; + + if (detected_fields) { + const properties = computeMappingProperties(detected_fields); + simulationBody.component_template_substitutions = { + [`${path.id}@stream.layer`]: { + template: { + mappings: { + properties, + }, + }, + }, + }; + } + + return simulationBody; +}; + +// TODO: update type once Kibana updates to elasticsearch-js 8.17 +const executeSimulation = async ( + scopedClusterClient: IScopedClusterClient, + simulationBody: ReturnType +): Promise => { + try { + // TODO: We should be using scopedClusterClient.asCurrentUser.simulate.ingest() once Kibana updates to elasticsearch-js 8.17 + return await scopedClusterClient.asCurrentUser.transport.request({ + method: 'POST', + path: `_ingest/_simulate`, + body: simulationBody, + }); + } catch (error) { + throw new SimulationFailed(error); + } +}; + +const assertSimulationResult = ( + simulationResult: Awaited>, + simulationDiffs: ReturnType +) => { + // Assert mappings are compatible with the documents + const entryWithError = simulationResult.docs.find(isMappingFailure); + if (entryWithError) { + throw new DetectedMappingFailure( + `The detected field types might not be compatible with these documents. ${entryWithError.doc.error.reason}` + ); + } + // Assert that the processors are purely additive to the documents + const updatedFields = computeUpdatedFields(simulationDiffs); + if (!isEmpty(updatedFields)) { + throw new NonAdditiveProcessor( + `The processor is not additive to the documents. It might update fields [${updatedFields.join()}]` + ); + } +}; + +const prepareSimulationResponse = ( + simulationResult: any, + docs: Array<{ _source: Record }>, + simulationDiffs: ReturnType, + detectedFields?: ProcessingSimulateParams['body']['detected_fields'] +) => { + const confirmedValidDetectedFields = computeMappingProperties(detectedFields ?? []); + const documents = computeSimulationDocuments(simulationResult, docs); + const detectedFieldsResult = computeDetectedFields(simulationDiffs, confirmedValidDetectedFields); + const successRate = computeSuccessRate(simulationResult); + const failureRate = 1 - successRate; + + return { + documents, + success_rate: parseFloat(successRate.toFixed(2)), + failure_rate: parseFloat(failureRate.toFixed(2)), + detected_fields: detectedFieldsResult, + }; +}; + +// TODO: update type once Kibana updates to elasticsearch-js 8.17 +const prepareSimulationDiffs = ( + simulation: any, sampleDocs: Array<{ _source: Record }> ) => { // Since we filter out failed documents, we need to map the simulation docs to the sample docs for later retrieval - const samplesToSimulationMap = new Map(simulation.docs.map((doc, id) => [doc, sampleDocs[id]])); + const samplesToSimulationMap = new Map }>( + simulation.docs.map((entry: any, id: number) => [entry.doc, sampleDocs[id]]) + ); - const diffs = simulation.docs.filter(isSuccessfulDocument).map((doc) => { - const sample = samplesToSimulationMap.get(doc); + const diffs = simulation.docs.filter(isSuccessfulDocument).map((entry: any) => { + const sample = samplesToSimulationMap.get(entry.doc); if (sample) { - return calculateObjectDiff(sample._source, doc.processor_results.at(-1)?.doc?._source); + return calculateObjectDiff(sample._source, entry.doc._source); } return calculateObjectDiff({}); @@ -117,9 +203,10 @@ const computeSimulationDiffs = ( return diffs; }; -const computeUpdatedFields = (simulationDiff: ReturnType) => { +// TODO: update type once Kibana updates to elasticsearch-js 8.17 +const computeUpdatedFields = (simulationDiff: ReturnType) => { const diffs = simulationDiff - .map((simulatedDoc) => flattenObject(simulatedDoc.updated)) + .map((simulatedDoc: any) => flattenObject(simulatedDoc.updated)) .flatMap(Object.keys); const uniqueFields = [...new Set(diffs)]; @@ -127,15 +214,16 @@ const computeUpdatedFields = (simulationDiff: ReturnType }> -) => { - return simulation.docs.map((doc, id) => { +): Array<{ isMatch: boolean; value: Record }> => { + return simulation.docs.map((entry: any, id: number) => { // If every processor was successful, return and flatten the simulation doc from the last processor - if (isSuccessfulDocument(doc)) { + if (isSuccessfulDocument(entry)) { return { - value: flattenObject(doc.processor_results.at(-1)?.doc?._source ?? sampleDocs[id]._source), + value: flattenObject(entry.doc._source ?? sampleDocs[id]._source), isMatch: true, }; } @@ -148,32 +236,44 @@ const computeSimulationDocuments = ( }; const computeDetectedFields = ( - simulationDiff: ReturnType + simulationDiff: ReturnType, + confirmedValidDetectedFields: Record ): Array<{ name: string; type: FieldDefinitionConfig['type'] | 'unmapped'; }> => { - const diffs = simulationDiff - .map((simulatedDoc) => flattenObject(simulatedDoc.added)) + const diffs: string[] = simulationDiff + .map((simulatedDoc: any) => flattenObject(simulatedDoc.added)) .flatMap(Object.keys); const uniqueFields = [...new Set(diffs)]; - return uniqueFields.map((name) => ({ name, type: 'unmapped' })); + return uniqueFields.map((name: string) => ({ + name, + type: confirmedValidDetectedFields[name]?.type || 'unmapped', + })); }; -const computeSuccessRate = (simulation: IngestSimulateResponse) => { - const successfulCount = simulation.docs.reduce((rate, doc) => { - return (rate += isSuccessfulDocument(doc) ? 1 : 0); +// TODO: update type once Kibana updates to elasticsearch-js 8.17 +const computeSuccessRate = (simulation: any) => { + const successfulCount = simulation.docs.reduce((rate: number, entry: any) => { + return (rate += isSuccessfulDocument(entry) ? 1 : 0); }, 0); + return successfulCount / simulation.docs.length; }; -const isSuccessfulDocument = ( - doc: IngestSimulateSimulateDocumentResult -): doc is Required => - doc.processor_results?.every((processorSimulation) => processorSimulation.status === 'success') || - false; +const computeMappingProperties = ( + detectedFields: NonNullable +) => { + return Object.fromEntries(detectedFields.map(({ name, type }) => [name, { type }])); +}; + +// TODO: update type once Kibana updates to elasticsearch-js 8.17 +const isSuccessfulDocument = (entry: any) => entry.doc.error === undefined; +// TODO: update type once Kibana updates to elasticsearch-js 8.17 +const isMappingFailure = (entry: any) => + !isSuccessfulDocument(entry) && entry.doc.error.type === 'document_parsing_exception'; export const processingRoutes = { ...simulateProcessorRoute, diff --git a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/dissect/dissect_pattern_definition.tsx b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/dissect/dissect_pattern_definition.tsx index 80d9245c61971..cb4e3559e480a 100644 --- a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/dissect/dissect_pattern_definition.tsx +++ b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/dissect/dissect_pattern_definition.tsx @@ -12,12 +12,13 @@ import { CodeEditor } from '@kbn/code-editor'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { useKibana } from '../../../../hooks/use_kibana'; +import { ProcessorFormState } from '../../types'; export const DissectPatternDefinition = () => { const { core } = useKibana(); const esDocUrl = core.docLinks.links.ingest.dissectKeyModifiers; - const { field, fieldState } = useController({ + const { field, fieldState } = useController({ name: 'pattern', rules: { required: i18n.translate( diff --git a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/grok/grok_pattern_definition.tsx b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/grok/grok_pattern_definition.tsx index 1cfa43a904867..b0a9bd50b95eb 100644 --- a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/grok/grok_pattern_definition.tsx +++ b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/grok/grok_pattern_definition.tsx @@ -10,9 +10,12 @@ import { useController } from 'react-hook-form'; import { EuiFormRow } from '@elastic/eui'; import { CodeEditor } from '@kbn/code-editor'; import { i18n } from '@kbn/i18n'; +import { ProcessorFormState } from '../../types'; export const GrokPatternDefinition = () => { - const { field, fieldState } = useController({ name: 'pattern_definitions' }); + const { field, fieldState } = useController({ + name: 'pattern_definitions', + }); return ( diff --git a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/index.tsx b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/index.tsx index bd04e2cbf959e..27624933559b2 100644 --- a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/index.tsx +++ b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/index.tsx @@ -68,7 +68,7 @@ export function AddProcessorFlyout({ const handleSubmit: SubmitHandler = async (data) => { const processingDefinition = convertFormStateToProcessing(data); - simulate(processingDefinition).then((responseBody) => { + simulate(processingDefinition, data.detected_fields).then((responseBody) => { if (responseBody instanceof Error) return; onAddProcessor(processingDefinition, data.detected_fields); diff --git a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/processor_condition_editor.tsx b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/processor_condition_editor.tsx index 51a57bf6b14df..eca584d8d2e71 100644 --- a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/processor_condition_editor.tsx +++ b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/processor_condition_editor.tsx @@ -8,9 +8,10 @@ import React from 'react'; import { useController } from 'react-hook-form'; import { ConditionEditor } from '../../condition_editor'; +import { ProcessorFormState } from '../types'; export const ProcessorConditionEditor = () => { - const { field } = useController({ name: 'condition' }); + const { field } = useController({ name: 'condition' }); return ; }; diff --git a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/processor_field_selector.tsx b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/processor_field_selector.tsx index 3fb52254f5d45..4486fdfa84700 100644 --- a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/processor_field_selector.tsx +++ b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/processor_field_selector.tsx @@ -9,9 +9,10 @@ import { EuiFormRow, EuiFieldText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { useController } from 'react-hook-form'; +import { ProcessorFormState } from '../types'; export const ProcessorFieldSelector = () => { - const { field, fieldState } = useController({ + const { field, fieldState } = useController({ name: 'field', rules: { required: i18n.translate( diff --git a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/processor_outcome_preview.tsx b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/processor_outcome_preview.tsx index 47a08264b70ab..167675bead535 100644 --- a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/processor_outcome_preview.tsx +++ b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/processor_outcome_preview.tsx @@ -31,7 +31,7 @@ import { ReadStreamDefinition, isWiredReadStream, } from '@kbn/streams-schema'; -import { useController, useFieldArray } from 'react-hook-form'; +import { UseControllerProps, useController, useFieldArray } from 'react-hook-form'; import { css } from '@emotion/react'; import { flattenObject } from '@kbn/object-utils'; import { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public'; @@ -109,7 +109,8 @@ export const ProcessorOutcomePreview = ({ }, [formFields.field, detectedFieldsColumns, selectedDocsFilter]); const detectedFieldsEnabled = - isWiredReadStream(definition) && simulation && !isEmpty(simulation.detected_fields); + isWiredReadStream(definition) && + ((simulation && !isEmpty(simulation.detected_fields)) || !isEmpty(formFields.detected_fields)); return ( @@ -126,7 +127,9 @@ export const ProcessorOutcomePreview = ({ iconType="play" color="accentSecondary" size="s" - onClick={() => onSimulate(convertFormStateToProcessing(formFields))} + onClick={() => { + onSimulate(convertFormStateToProcessing(formFields), formFields.detected_fields); + }} isLoading={isLoading} > {i18n.translate( @@ -136,7 +139,7 @@ export const ProcessorOutcomePreview = ({ - {detectedFieldsEnabled && } + {detectedFieldsEnabled && } { +const DetectedFields = ({ detectedFields }: { detectedFields?: DetectedField[] }) => { const { euiTheme } = useEuiTheme(); const { fields, replace } = useFieldArray<{ detected_fields: DetectedField[] }>({ name: 'detected_fields', }); useEffect(() => { - replace(detectedFields); + if (detectedFields) replace(detectedFields); }, [detectedFields, replace]); return ( @@ -287,17 +290,19 @@ const DetectedFields = ({ detectedFields }: { detectedFields: DetectedField[] }) > {fields.map((field, id) => ( - + ))} ); }; -const DetectedFieldSelector = ({ selectorId }: { selectorId: string }) => { - const { field } = useController({ name: selectorId }); +const DetectedFieldSelector = ( + props: UseControllerProps +) => { + const { field } = useController(props); - const options = useMemo(() => getDetectedFieldSelectOptions(field.value), [field]); + const options = useMemo(() => getDetectedFieldSelectOptions(field.value), [field.value]); return ( ({ + name: 'type', + rules: { required: true }, + }); const processorType = useWatch<{ type: ProcessorType }>({ name: 'type' }); @@ -74,7 +78,9 @@ const availableProcessors: TAvailableProcessors = { values={{ dissectLink: ( - dissect + {i18n.translate('xpack.streams.availableProcessors.dissectLinkLabel', { + defaultMessage: 'dissect', + })} ), }} @@ -91,7 +97,9 @@ const availableProcessors: TAvailableProcessors = { values={{ grokLink: ( - grok + {i18n.translate('xpack.streams.availableProcessors.grokLinkLabel', { + defaultMessage: 'grok', + })} ), }} diff --git a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/toggle_field.tsx b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/toggle_field.tsx index 47b38ff0dbcef..f5e70267b7ff9 100644 --- a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/toggle_field.tsx +++ b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/flyout/toggle_field.tsx @@ -8,12 +8,19 @@ import React from 'react'; import { useController } from 'react-hook-form'; import { EuiFormRow, EuiFormRowProps, EuiSwitch, htmlIdGenerator } from '@elastic/eui'; +import { ProcessorFormState } from '../types'; + +type ExtractBooleanFields = NonNullable< + { + [K in keyof TInput]: boolean extends TInput[K] ? K : never; + }[keyof TInput] +>; interface ToggleFieldProps { helpText?: EuiFormRowProps['helpText']; id?: string; label: string; - name: string; + name: ExtractBooleanFields; } export const ToggleField = ({ @@ -23,14 +30,16 @@ export const ToggleField = ({ name, ...rest }: ToggleFieldProps) => { - const { field } = useController({ name }); + const { field } = useController({ + name, + }); return ( field.onChange(e.target.checked)} /> diff --git a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/hooks/use_processing_simulator.ts b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/hooks/use_processing_simulator.ts index 1ff63fbc484e6..270984feec219 100644 --- a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/hooks/use_processing_simulator.ts +++ b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_enrichment/hooks/use_processing_simulator.ts @@ -5,23 +5,31 @@ * 2.0. */ +/* eslint-disable @typescript-eslint/naming-convention */ + import { useAbortController } from '@kbn/observability-utils-browser/hooks/use_abort_controller'; import { ReadStreamDefinition, ProcessingDefinition, Condition } from '@kbn/streams-schema'; import useAsyncFn from 'react-use/lib/useAsyncFn'; import { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public'; import { useDateRange } from '@kbn/observability-utils-browser/hooks/use_date_range'; -import { APIReturnType } from '@kbn/streams-plugin/public/api'; +import { APIReturnType, StreamsAPIClientRequestParamsOf } from '@kbn/streams-plugin/public/api'; import { useStreamsAppFetch } from '../../../hooks/use_streams_app_fetch'; import { useKibana } from '../../../hooks/use_kibana'; +import { DetectedField } from '../types'; type Simulation = APIReturnType<'POST /api/streams/{id}/processing/_simulate'>; +type SimulationRequestBody = + StreamsAPIClientRequestParamsOf<'POST /api/streams/{id}/processing/_simulate'>['params']['body']; export interface UseProcessingSimulatorReturnType { error?: IHttpFetchError; isLoading: boolean; refreshSamples: () => void; samples: Array>; - simulate: (processing: ProcessingDefinition) => Promise; + simulate: ( + processing: ProcessingDefinition, + detectedFields?: DetectedField[] + ) => Promise; simulation?: Simulation | null; } @@ -64,7 +72,7 @@ export const useProcessingSimulator = ({ condition, start: start?.valueOf(), end: end?.valueOf(), - number: 100, + size: 100, }, }, }); @@ -76,11 +84,17 @@ export const useProcessingSimulator = ({ const sampleDocs = (samples?.documents ?? []) as Array>; const [{ loading: isLoadingSimulation, error, value }, simulate] = useAsyncFn( - (processingDefinition: ProcessingDefinition) => { + (processingDefinition: ProcessingDefinition, detectedFields?: DetectedField[]) => { if (!definition) { return Promise.resolve(null); } + const detected_fields = detectedFields + ? (detectedFields.filter( + (field) => field.type !== 'unmapped' + ) as SimulationRequestBody['detected_fields']) + : undefined; + return streamsRepositoryClient.fetch('POST /api/streams/{id}/processing/_simulate', { signal: abortController.signal, params: { @@ -88,6 +102,7 @@ export const useProcessingSimulator = ({ body: { documents: sampleDocs, processing: [processingDefinition], + detected_fields, }, }, }); diff --git a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_routing/index.tsx b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_routing/index.tsx index 094811795ac4e..74c650c93728f 100644 --- a/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_routing/index.tsx +++ b/x-pack/solutions/observability/plugins/streams_app/public/components/stream_detail_routing/index.tsx @@ -507,7 +507,7 @@ function PreviewPanel({ condition: routingAppState.debouncedChildUnderEdit.child.condition, start: start?.valueOf(), end: end?.valueOf(), - number: 100, + size: 100, }, }, }); diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_alerts.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_alerts.tsx index 40bcaa3697b30..690ce9303d2b9 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_alerts.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_alerts.tsx @@ -12,7 +12,6 @@ import { EuiSkeletonText, EuiText, EuiTitle, - euiPaletteColorBlindBehindText, useEuiTheme, } from '@elastic/eui'; import { RECORDS_FIELD } from '@kbn/exploratory-view-plugin/public'; @@ -148,7 +147,7 @@ export const MonitorAlerts = ({ ...(locationFilter ?? []), ], color: isAmsterdam - ? euiPaletteColorBlindBehindText()[7] + ? euiTheme.colors.vis.euiColorVisBehindText7 : euiTheme.colors.vis.euiColorVis7, }, ]} @@ -203,7 +202,7 @@ export const MonitorAlerts = ({ ...(locationFilter ?? []), ], color: isAmsterdam - ? euiPaletteColorBlindBehindText()[0] + ? euiTheme.colors.vis.euiColorVisBehindText0 : euiTheme.colors.vis.euiColorVis0, }, ]} diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item.tsx index 7121268f4661f..58406d8e6555d 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item.tsx @@ -5,13 +5,7 @@ * 2.0. */ import { Chart, Metric, MetricTrendShape, Settings } from '@elastic/charts'; -import { - EuiPanel, - EuiSpacer, - EuiThemeComputed, - euiPaletteColorBlindBehindText, - useEuiTheme, -} from '@elastic/eui'; +import { EuiPanel, EuiSpacer, EuiThemeComputed, useEuiTheme } from '@elastic/eui'; import { css } from '@emotion/react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; @@ -49,13 +43,13 @@ export const getColor = (euiTheme: EuiThemeComputed, isEnabled: boolean, status? switch (status) { case 'down': - return isAmsterdam ? euiPaletteColorBlindBehindText()[9] : euiTheme.colors.danger; + return isAmsterdam ? euiTheme.colors.vis.euiColorVisBehindText9 : euiTheme.colors.danger; case 'up': - return isAmsterdam ? euiPaletteColorBlindBehindText()[0] : euiTheme.colors.success; + return isAmsterdam ? euiTheme.colors.vis.euiColorVisBehindText0 : euiTheme.colors.success; case 'unknown': return euiTheme.colors.ghost; default: - return isAmsterdam ? euiPaletteColorBlindBehindText()[0] : euiTheme.colors.success; + return isAmsterdam ? euiTheme.colors.vis.euiColorVisBehindText0 : euiTheme.colors.success; } }; diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/hooks/use_status_by_location.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/hooks/use_status_by_location.tsx index a4706794ad26d..f37c087a045d7 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/hooks/use_status_by_location.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/hooks/use_status_by_location.tsx @@ -75,11 +75,13 @@ export function useStatusByLocation({ return useMemo(() => { const getColor = (status: string) => { + const isAmsterdam = euiTheme.themeName === 'EUI_THEME_AMSTERDAM'; + switch (status) { case 'up': - return euiTheme.colors.success; + return isAmsterdam ? euiTheme.colors.vis.euiColorVis0 : euiTheme.colors.success; case 'down': - return euiTheme.colors.vis.euiColorVis6; + return isAmsterdam ? euiTheme.colors.vis.euiColorVis9 : euiTheme.colors.vis.euiColorVis6; default: return euiTheme.colors.backgroundBaseSubdued; } @@ -113,8 +115,11 @@ export function useStatusByLocation({ data?.aggregations?.locations.buckets, loading, monitorLocations, + euiTheme.themeName, euiTheme.colors.success, + euiTheme.colors.vis.euiColorVis0, euiTheme.colors.vis.euiColorVis6, + euiTheme.colors.vis.euiColorVis9, euiTheme.colors.backgroundBaseSubdued, ]); } diff --git a/x-pack/solutions/observability/plugins/synthetics/server/telemetry/sender.test.ts b/x-pack/solutions/observability/plugins/synthetics/server/telemetry/sender.test.ts index 91f859545600b..82c0f096c4f30 100644 --- a/x-pack/solutions/observability/plugins/synthetics/server/telemetry/sender.test.ts +++ b/x-pack/solutions/observability/plugins/synthetics/server/telemetry/sender.test.ts @@ -19,6 +19,7 @@ import { MONITOR_UPDATE_CHANNEL } from './constants'; import { TelemetryEventsSender } from './sender'; import { LicenseGetResponse } from '@elastic/elasticsearch/lib/api/types'; +import { Observable } from 'rxjs'; jest.mock('axios', () => { return { @@ -87,6 +88,7 @@ describe('TelemetryEventsSender', () => { it('should send events when due', async () => { sender['telemetryStart'] = { getIsOptedIn: jest.fn(async () => true), + isOptedIn$: new Observable(), }; sender['telemetrySetup'] = { getTelemetryUrl: jest.fn( @@ -108,6 +110,7 @@ describe('TelemetryEventsSender', () => { it("shouldn't send when telemetry is disabled", async () => { const telemetryStart = { getIsOptedIn: jest.fn(async () => false), + isOptedIn$: new Observable(), }; sender['telemetryStart'] = telemetryStart; @@ -122,6 +125,7 @@ describe('TelemetryEventsSender', () => { it('should send events to separate channels', async () => { sender['telemetryStart'] = { getIsOptedIn: jest.fn(async () => true), + isOptedIn$: new Observable(), }; sender['telemetrySetup'] = { getTelemetryUrl: jest.fn( diff --git a/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/monitor/ping_list/columns/ping_status.tsx b/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/monitor/ping_list/columns/ping_status.tsx index 9e5fef631507c..64608c6c4b445 100644 --- a/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/monitor/ping_list/columns/ping_status.tsx +++ b/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/monitor/ping_list/columns/ping_status.tsx @@ -32,7 +32,11 @@ const getPingStatusLabel = (status: string, ping: Ping) => { export const PingStatusColumn = ({ pingStatus, item }: Props) => { const theme = useEuiTheme(); - const dangerBehindText = theme.euiTheme.colors.textDanger; + const isAmsterdam = theme.euiTheme.themeName === 'EUI_THEME_AMSTERDAM'; + + const dangerBehindText = isAmsterdam + ? theme.euiTheme.colors.vis.euiColorVisBehindText9 + : theme.euiTheme.colors.vis.euiColorVis6; const timeStamp = moment(item.timestamp); diff --git a/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/overview/monitor_list/columns/status_badge.tsx b/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/overview/monitor_list/columns/status_badge.tsx index 5abf56c0189e5..55dc1f3cd6889 100644 --- a/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/overview/monitor_list/columns/status_badge.tsx +++ b/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/overview/monitor_list/columns/status_badge.tsx @@ -19,7 +19,11 @@ export const StatusBadge = ({ summaryError?: PingError; }) => { const theme = useEuiTheme(); - const dangerBehindText = theme.euiTheme.colors.textDanger; + const isAmsterdam = theme.euiTheme.themeName === 'EUI_THEME_AMSTERDAM'; + + const dangerBehindText = isAmsterdam + ? theme.euiTheme.colors.vis.euiColorVisBehindText9 + : theme.euiTheme.colors.vis.euiColorVis6; if (status === STATUS.UP) { return ( diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/plugin.ts b/x-pack/solutions/search/plugins/enterprise_search/public/plugin.ts index e71a548135eb1..66e375443e383 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/public/plugin.ts +++ b/x-pack/solutions/search/plugins/enterprise_search/public/plugin.ts @@ -58,8 +58,10 @@ import { hasEnterpriseLicense } from '../common/utils/licensing'; import { SEARCH_APPLICATIONS_PATH } from './applications/applications/routes'; import { CONNECTORS_PATH, CRAWLERS_PATH } from './applications/enterprise_search_content/routes'; - import { docLinks } from './applications/shared/doc_links'; +import connectorIcon from './assets/images/connector.svg'; +import crawlerIcon from './assets/images/crawler.svg'; + import type { DynamicSideNavItems } from './navigation_tree'; export interface ClientData extends InitialAppData { @@ -107,6 +109,7 @@ export type UpdateSideNavDefinitionFn = (items: Partial) => const contentLinks: AppDeepLink[] = [ { + euiIconType: connectorIcon, id: 'connectors', path: `/${CONNECTORS_PATH}`, title: i18n.translate('xpack.enterpriseSearch.navigation.contentConnectorsLinkLabel', { @@ -114,6 +117,7 @@ const contentLinks: AppDeepLink[] = [ }), }, { + euiIconType: crawlerIcon, id: 'webCrawlers', path: `/${CRAWLERS_PATH}`, title: i18n.translate('xpack.enterpriseSearch.navigation.contentWebcrawlersLinkLabel', { diff --git a/x-pack/solutions/search/plugins/enterprise_search/server/integrations.ts b/x-pack/solutions/search/plugins/enterprise_search/server/integrations.ts index cc1682386642b..cca2c84aa8555 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/server/integrations.ts +++ b/x-pack/solutions/search/plugins/enterprise_search/server/integrations.ts @@ -11,23 +11,24 @@ import { ConfigType } from '.'; export const registerEnterpriseSearchIntegrations = ( config: ConfigType, - customIntegrations: CustomIntegrationsPluginSetup + customIntegrations: CustomIntegrationsPluginSetup, + crawlerAssetBasePath: string ) => { if (config.hasWebCrawler) { customIntegrations.registerCustomIntegration({ id: 'web_crawler', title: i18n.translate('xpack.enterpriseSearch.integrations.webCrawlerName', { - defaultMessage: 'Web crawler', + defaultMessage: 'Web Crawler', }), description: i18n.translate('xpack.enterpriseSearch.integrations.webCrawlerDescription', { defaultMessage: 'Add search to your website with the web crawler.', }), categories: ['search', 'web', 'elastic_stack', 'crawler'], - uiInternalPath: '/app/elasticsearch/content/crawlers/new_crawler', + uiInternalPath: '/app/elasticsearch/content/crawlers', icons: [ { - type: 'eui', - src: 'logoEnterpriseSearch', + type: 'svg', + src: crawlerAssetBasePath, }, ], shipper: 'search', diff --git a/x-pack/solutions/search/plugins/enterprise_search/server/plugin.ts b/x-pack/solutions/search/plugins/enterprise_search/server/plugin.ts index aaa133986b2ff..e4657c3e8a373 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/server/plugin.ts +++ b/x-pack/solutions/search/plugins/enterprise_search/server/plugin.ts @@ -171,7 +171,11 @@ export class EnterpriseSearchPlugin implements Plugin { - const crawlerResult = { - icon: 'crawlerIcon.svg', - id: 'elastic-crawler', - score: 75, - title: 'Elastic Web Crawler', - type: 'Elasticsearch', - url: { - path: `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/crawlers/new_crawler`, - prependBasePath: true, - }, - }; - const mongoResult = { icon: 'mongodb.svg', id: 'mongodb', @@ -118,11 +106,9 @@ describe('Search search provider', () => { const searchResultProvider = getSearchResultProvider( { hasConnectors: true, - hasWebCrawler: true, } as any, connectors, - false, - 'crawlerIcon.svg' + false ); beforeEach(() => {}); @@ -132,20 +118,6 @@ describe('Search search provider', () => { }); describe('find', () => { - it('returns formatted results', () => { - getTestScheduler().run(({ expectObservable }) => { - expectObservable( - searchResultProvider.find( - { term: 'crawler' }, - { aborted$: NEVER, maxResults: 100, preference: '' }, - mockSearchProviderContext - ) - ).toBe('(a|)', { - a: [crawlerResult], - }); - }); - }); - it('returns everything on empty string', () => { getTestScheduler().run(({ expectObservable }) => { expectObservable( @@ -155,10 +127,7 @@ describe('Search search provider', () => { mockSearchProviderContext ) ).toBe('(a|)', { - a: expect.arrayContaining([ - { ...crawlerResult, score: 80 }, - { ...mongoResult, score: 80 }, - ]), + a: expect.arrayContaining([{ ...mongoResult, score: 80 }]), }); }); }); @@ -172,30 +141,7 @@ describe('Search search provider', () => { mockSearchProviderContext ) ).toBe('(a|)', { - a: [{ ...crawlerResult, score: 80 }], - }); - }); - }); - - it('omits crawler if config has crawler disabled', () => { - const searchProvider = getSearchResultProvider( - { - hasConnectors: true, - hasWebCrawler: false, - } as any, - connectors, - false, - 'crawlerIcon.svg' - ); - getTestScheduler().run(({ expectObservable }) => { - expectObservable( - searchProvider.find( - { term: '' }, - { aborted$: NEVER, maxResults: 100, preference: '' }, - mockSearchProviderContext - ) - ).toBe('(a|)', { - a: expect.not.arrayContaining([{ ...crawlerResult, score: 80 }]), + a: expect.arrayContaining([{ ...mongoResult, score: 80 }]), }); }); }); @@ -204,11 +150,9 @@ describe('Search search provider', () => { const searchProvider = getSearchResultProvider( { hasConnectors: false, - hasWebCrawler: true, } as any, connectors, - false, - 'crawlerIcon.svg' + false ); getTestScheduler().run(({ expectObservable }) => { expectObservable( @@ -263,41 +207,13 @@ describe('Search search provider', () => { }); }); }); - it('returns results for integrations tag', () => { - getTestScheduler().run(({ expectObservable }) => { - expectObservable( - searchResultProvider.find( - { term: 'crawler', types: ['integration'] }, - { aborted$: NEVER, maxResults: 1, preference: '' }, - mockSearchProviderContext - ) - ).toBe('(a|)', { - a: [crawlerResult], - }); - }); - }); - it('returns results for enterprise search tag', () => { - getTestScheduler().run(({ expectObservable }) => { - expectObservable( - searchResultProvider.find( - { term: 'crawler', types: ['enterprise search'] }, - { aborted$: NEVER, maxResults: 1, preference: '' }, - mockSearchProviderContext - ) - ).toBe('(a|)', { - a: [crawlerResult], - }); - }); - }); it('does not return results for legacy app search', () => { const searchProvider = getSearchResultProvider( { hasConnectors: false, - hasWebCrawler: false, } as any, connectors, - false, - 'crawlerIcon.svg' + false ); getTestScheduler().run(({ expectObservable }) => { expectObservable( @@ -315,11 +231,9 @@ describe('Search search provider', () => { const searchProvider = getSearchResultProvider( { hasConnectors: false, - hasWebCrawler: false, } as any, connectors, - false, - 'crawlerIcon.svg' + false ); getTestScheduler().run(({ expectObservable }) => { expectObservable( @@ -338,11 +252,9 @@ describe('Search search provider', () => { const searchProvider = getSearchResultProvider( { hasConnectors: true, - hasWebCrawler: true, } as any, connectors, - true, - 'crawlerIcon.svg' + true ); getTestScheduler().run(({ expectObservable }) => { expectObservable( @@ -353,7 +265,6 @@ describe('Search search provider', () => { ) ).toBe('(a|)', { a: expect.arrayContaining([ - { ...crawlerResult, score: 80 }, { ...nativeMongoResult, score: 80 }, { ...customizedConnectorResult, score: 80 }, ]), diff --git a/x-pack/solutions/search/plugins/enterprise_search/server/utils/search_result_provider.ts b/x-pack/solutions/search/plugins/enterprise_search/server/utils/search_result_provider.ts index 6da354495ea0d..47c99f1e59461 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/server/utils/search_result_provider.ts +++ b/x-pack/solutions/search/plugins/enterprise_search/server/utils/search_result_provider.ts @@ -73,8 +73,7 @@ export function toSearchResult({ export function getSearchResultProvider( config: ConfigType, connectorTypes: ConnectorServerSideDefinition[], - isCloud: boolean, - crawlerIconPath: string + isCloud: boolean ): GlobalSearchResultProvider { return { find: ({ term, types, tags }, { aborted$, maxResults }, { core: { capabilities } }) => { @@ -93,18 +92,6 @@ export function getSearchResultProvider( } const services: ServiceDefinition[] = [ - ...(config.hasWebCrawler - ? [ - { - iconPath: crawlerIconPath, - keywords: ['crawler', 'web', 'website', 'internet', 'google'], - name: i18n.translate('xpack.enterpriseSearch.searchProvider.webCrawler.name', { - defaultMessage: 'Elastic Web Crawler', - }), - serviceType: ENTERPRISE_SEARCH_CONNECTOR_CRAWLER_SERVICE_TYPE, - }, - ] - : []), ...(config.hasConnectors ? connectorTypes : []), { diff --git a/x-pack/solutions/search/plugins/search_indices/public/analytics/constants.ts b/x-pack/solutions/search/plugins/search_indices/public/analytics/constants.ts index 0da7aedf19328..fe7c19eeb708c 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/analytics/constants.ts +++ b/x-pack/solutions/search/plugins/search_indices/public/analytics/constants.ts @@ -11,12 +11,15 @@ export enum AnalyticsEvents { startPageShowCreateIndexUIClick = 'start_page_show_create_index_ui', startCreateIndexPageModifyIndexName = 'start_modify_index_name', startCreateIndexClick = 'start_create_index', + startCreateIndexWorkflowSelect = 'start_workflow_select', startCreateIndexLanguageSelect = 'start_code_lang_select', startCreateIndexRunInConsole = 'start_cta_run_in_console', startCreateIndexCodeCopyInstall = 'start_code_copy_install', startCreateIndexCodeCopy = 'start_code_copy', startCreateIndexCreatedRedirect = 'start_index_created_api', startFileUploadClick = 'start_file_upload', + indexDetailsCodeLanguageSelect = 'index_details_code_lang_select', + indexDetailsWorkflowSelect = 'index_details_workflow_select', indexDetailsInstallCodeCopy = 'index_details_code_copy_install', indexDetailsAddMappingsCodeCopy = 'index_details_add_mappings_code_copy', indexDetailsIngestDocumentsCodeCopy = 'index_details_ingest_documents_code_copy', @@ -29,6 +32,7 @@ export enum AnalyticsEvents { createIndexPageModifyIndexName = 'create_index_modify_index_name', createIndexCreateIndexClick = 'create_index_click_create', createIndexLanguageSelect = 'create_index_code_lang_select', + createIndexWorkflowSelect = 'create_index_workflow_select', createIndexRunInConsole = 'create_index_run_in_console', createIndexCodeCopyInstall = 'create_index_copy_install', createIndexCodeCopy = 'create_index_code_copy', diff --git a/x-pack/solutions/search/plugins/search_indices/public/code_examples/constants.ts b/x-pack/solutions/search/plugins/search_indices/public/code_examples/constants.ts index 3ba23d0fae222..aca4c4c5e4bb2 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/code_examples/constants.ts +++ b/x-pack/solutions/search/plugins/search_indices/public/code_examples/constants.ts @@ -34,3 +34,31 @@ export const CONNECT_CREATE_VECTOR_INDEX_CMD_DESCRIPTION = i18n.translate( defaultMessage: 'Use the Elasticsearch client to create an index with dense vector fields', } ); + +export const CONNECT_CREATE_DEFAULT_INDEX_CMD_TITLE = i18n.translate( + 'xpack.searchIndices.code.createIndexCommand.title', + { + defaultMessage: 'Create an index with text fields', + } +); + +export const CONNECT_CREATE_DEFAULT_INDEX_CMD_DESCRIPTION = i18n.translate( + 'xpack.searchIndices.code.createIndexCommand.description', + { + defaultMessage: 'Use the Elasticsearch client to create an index with text fields', + } +); + +export const CONNECT_CREATE_SEMANTIC_INDEX_CMD_TITLE = i18n.translate( + 'xpack.searchIndices.code.createIndexCommand.title', + { + defaultMessage: 'Create an index with semantic fields', + } +); + +export const CONNECT_CREATE_SEMANTIC_INDEX_CMD_DESCRIPTION = i18n.translate( + 'xpack.searchIndices.code.createIndexCommand.description', + { + defaultMessage: 'Use the Elasticsearch client to create an index with semantic fields', + } +); diff --git a/x-pack/solutions/search/plugins/search_indices/public/code_examples/create_index.ts b/x-pack/solutions/search/plugins/search_indices/public/code_examples/create_index.ts index d462c2310ab4c..d77ac7ce49416 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/code_examples/create_index.ts +++ b/x-pack/solutions/search/plugins/search_indices/public/code_examples/create_index.ts @@ -7,6 +7,10 @@ import { CreateIndexCodeExamples } from '../types'; import { + CONNECT_CREATE_DEFAULT_INDEX_CMD_DESCRIPTION, + CONNECT_CREATE_DEFAULT_INDEX_CMD_TITLE, + CONNECT_CREATE_SEMANTIC_INDEX_CMD_DESCRIPTION, + CONNECT_CREATE_SEMANTIC_INDEX_CMD_TITLE, CONNECT_CREATE_VECTOR_INDEX_CMD_DESCRIPTION, CONNECT_CREATE_VECTOR_INDEX_CMD_TITLE, INSTALL_INSTRUCTIONS_DESCRIPTION, @@ -14,23 +18,23 @@ import { } from './constants'; import { CurlCreateIndexExamples } from './curl'; -import { JavascriptServerlessCreateIndexExamples } from './javascript'; -import { PythonServerlessCreateIndexExamples } from './python'; +import { JavascriptCreateIndexExamples } from './javascript'; +import { PythonCreateIndexExamples } from './python'; import { ConsoleCreateIndexExamples } from './sense'; -export const DefaultServerlessCodeExamples: CreateIndexCodeExamples = { +export const DefaultCodeExamples: CreateIndexCodeExamples = { exampleType: 'search', installTitle: INSTALL_INSTRUCTIONS_TITLE, installDescription: INSTALL_INSTRUCTIONS_DESCRIPTION, - createIndexTitle: CONNECT_CREATE_VECTOR_INDEX_CMD_TITLE, - createIndexDescription: CONNECT_CREATE_VECTOR_INDEX_CMD_DESCRIPTION, + createIndexTitle: CONNECT_CREATE_DEFAULT_INDEX_CMD_TITLE, + createIndexDescription: CONNECT_CREATE_DEFAULT_INDEX_CMD_DESCRIPTION, sense: ConsoleCreateIndexExamples.default, curl: CurlCreateIndexExamples.default, - python: PythonServerlessCreateIndexExamples.default, - javascript: JavascriptServerlessCreateIndexExamples.default, + python: PythonCreateIndexExamples.default, + javascript: JavascriptCreateIndexExamples.default, }; -export const DenseVectorSeverlessCodeExamples: CreateIndexCodeExamples = { +export const DenseVectorCodeExamples: CreateIndexCodeExamples = { exampleType: 'vector', installTitle: INSTALL_INSTRUCTIONS_TITLE, installDescription: INSTALL_INSTRUCTIONS_DESCRIPTION, @@ -38,6 +42,18 @@ export const DenseVectorSeverlessCodeExamples: CreateIndexCodeExamples = { createIndexDescription: CONNECT_CREATE_VECTOR_INDEX_CMD_DESCRIPTION, sense: ConsoleCreateIndexExamples.dense_vector, curl: CurlCreateIndexExamples.dense_vector, - python: PythonServerlessCreateIndexExamples.dense_vector, - javascript: JavascriptServerlessCreateIndexExamples.dense_vector, + python: PythonCreateIndexExamples.dense_vector, + javascript: JavascriptCreateIndexExamples.dense_vector, +}; + +export const SemanticCodeExamples: CreateIndexCodeExamples = { + exampleType: 'semantic', + installTitle: INSTALL_INSTRUCTIONS_TITLE, + installDescription: INSTALL_INSTRUCTIONS_DESCRIPTION, + createIndexTitle: CONNECT_CREATE_SEMANTIC_INDEX_CMD_TITLE, + createIndexDescription: CONNECT_CREATE_SEMANTIC_INDEX_CMD_DESCRIPTION, + sense: ConsoleCreateIndexExamples.semantic, + curl: CurlCreateIndexExamples.semantic, + python: PythonCreateIndexExamples.semantic, + javascript: JavascriptCreateIndexExamples.semantic, }; diff --git a/x-pack/solutions/search/plugins/search_indices/public/code_examples/curl.ts b/x-pack/solutions/search/plugins/search_indices/public/code_examples/curl.ts index a73d5a7cfe617..23fe480f216dc 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/code_examples/curl.ts +++ b/x-pack/solutions/search/plugins/search_indices/public/code_examples/curl.ts @@ -23,7 +23,16 @@ export const CurlCreateIndexExamples: CreateIndexLanguageExamples = { indexName ?? INDEX_PLACEHOLDER }' \ --header 'Authorization: ApiKey ${apiKey ?? API_KEY_PLACEHOLDER}' \ ---header 'Content-Type: application/json'`, +--header 'Content-Type: application/json +--data-raw '{ + "mappings": { + "properties":{ + "text":{ + "type":"text" + } + } + } +}'`, }, dense_vector: { createIndex: ({ elasticsearchURL, apiKey, indexName }) => `curl PUT '${elasticsearchURL}/${ @@ -43,11 +52,27 @@ export const CurlCreateIndexExamples: CreateIndexLanguageExamples = { } } } +}'`, + }, + semantic: { + createIndex: ({ elasticsearchURL, apiKey, indexName }) => `curl PUT '${elasticsearchURL}/${ + indexName ?? INDEX_PLACEHOLDER + }' \ +--header 'Authorization: ApiKey ${apiKey ?? API_KEY_PLACEHOLDER}' \ +--header 'Content-Type: application/json +--data-raw '{ + "mappings": { + "properties":{ + "text":{ + "type":"semantic_text" + } + } + } }'`, }, }; -export const CurlVectorsIngestDataExample: IngestDataCodeDefinition = { +export const CurlIngestDataExample: IngestDataCodeDefinition = { ingestCommand: ({ elasticsearchURL, apiKey, indexName, sampleDocuments }) => { let result = `curl -X POST "${elasticsearchURL}/_bulk?pretty" \ --header 'Authorization: ApiKey ${apiKey ?? API_KEY_PLACEHOLDER}' \ diff --git a/x-pack/solutions/search/plugins/search_indices/public/code_examples/ingest_data.ts b/x-pack/solutions/search/plugins/search_indices/public/code_examples/ingest_data.ts index f2eb019bda3e9..3f60109dd32e1 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/code_examples/ingest_data.ts +++ b/x-pack/solutions/search/plugins/search_indices/public/code_examples/ingest_data.ts @@ -8,21 +8,43 @@ import { i18n } from '@kbn/i18n'; import { IngestDataCodeExamples } from '../types'; -import { JSServerlessIngestVectorDataExample } from './javascript'; -import { PythonServerlessVectorsIngestDataExample } from './python'; -import { ConsoleVectorsIngestDataExample } from './sense'; -import { CurlVectorsIngestDataExample } from './curl'; +import { JSIngestDataExample } from './javascript'; +import { PythonIngestDataExample } from './python'; +import { ConsoleIngestDataExample } from './sense'; +import { CurlIngestDataExample } from './curl'; import { INSTALL_INSTRUCTIONS_TITLE, INSTALL_INSTRUCTIONS_DESCRIPTION } from './constants'; -export const DenseVectorServerlessCodeExamples: IngestDataCodeExamples = { +const addMappingsTitle = i18n.translate( + 'xpack.searchIndices.codeExamples.serverless.denseVector.mappingsTitle', + { + defaultMessage: 'Define field mappings', + } +); + +export const DefaultIngestDataCodeExamples: IngestDataCodeExamples = { installTitle: INSTALL_INSTRUCTIONS_TITLE, installDescription: INSTALL_INSTRUCTIONS_DESCRIPTION, - addMappingsTitle: i18n.translate( - 'xpack.searchIndices.codeExamples.serverless.denseVector.mappingsTitle', + addMappingsTitle, + addMappingsDescription: i18n.translate( + 'xpack.searchIndices.codeExamples.serverless.default.mappingsDescription', { - defaultMessage: 'Define field mappings', + defaultMessage: + 'This example defines one field: a text field that will provide full-text search capabilities. You can add more field types by modifying the mappings in your API call, or in the mappings tab.', } ), + defaultMapping: { + text: { type: 'text' }, + }, + sense: ConsoleIngestDataExample, + curl: CurlIngestDataExample, + python: PythonIngestDataExample, + javascript: JSIngestDataExample, +}; + +export const DenseVectorIngestDataCodeExamples: IngestDataCodeExamples = { + installTitle: INSTALL_INSTRUCTIONS_TITLE, + installDescription: INSTALL_INSTRUCTIONS_DESCRIPTION, + addMappingsTitle, addMappingsDescription: i18n.translate( 'xpack.searchIndices.codeExamples.serverless.denseVector.mappingsDescription', { @@ -34,8 +56,29 @@ export const DenseVectorServerlessCodeExamples: IngestDataCodeExamples = { vector: { type: 'dense_vector', dims: 3 }, text: { type: 'text' }, }, - sense: ConsoleVectorsIngestDataExample, - curl: CurlVectorsIngestDataExample, - python: PythonServerlessVectorsIngestDataExample, - javascript: JSServerlessIngestVectorDataExample, + sense: ConsoleIngestDataExample, + curl: CurlIngestDataExample, + python: PythonIngestDataExample, + javascript: JSIngestDataExample, +}; + +export const SemanticIngestDataCodeExamples: IngestDataCodeExamples = { + installTitle: INSTALL_INSTRUCTIONS_TITLE, + installDescription: INSTALL_INSTRUCTIONS_DESCRIPTION, + addMappingsTitle, + addMappingsDescription: i18n.translate( + 'xpack.searchIndices.codeExamples.serverless.denseVector.mappingsDescription', + { + defaultMessage: + 'This example defines one field: a semantic text field that will provide vector search capabilities using the default ELSER model. You can add more field types by modifying the mappings in your API call, or in the mappings tab.', + } + ), + defaultMapping: { + // @ts-expect-error - our types don't understand yet that we can have semantic_text fields without inference ids + text: { type: 'semantic_text' }, + }, + sense: ConsoleIngestDataExample, + curl: CurlIngestDataExample, + python: PythonIngestDataExample, + javascript: JSIngestDataExample, }; diff --git a/x-pack/solutions/search/plugins/search_indices/public/code_examples/javascript.ts b/x-pack/solutions/search/plugins/search_indices/public/code_examples/javascript.ts index 75de93e485742..4da25de849068 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/code_examples/javascript.ts +++ b/x-pack/solutions/search/plugins/search_indices/public/code_examples/javascript.ts @@ -19,11 +19,11 @@ export const JAVASCRIPT_INFO: CodeLanguage = { codeBlockLanguage: 'javascript', }; -const SERVERLESS_INSTALL_CMD = `npm install @elastic/elasticsearch`; +const INSTALL_CMD = `npm install @elastic/elasticsearch`; -export const JavascriptServerlessCreateIndexExamples: CreateIndexLanguageExamples = { +export const JavascriptCreateIndexExamples: CreateIndexLanguageExamples = { default: { - installCommand: SERVERLESS_INSTALL_CMD, + installCommand: INSTALL_CMD, createIndex: ({ elasticsearchURL, apiKey, @@ -39,10 +39,15 @@ const client = new Client({ client.indices.create({ index: "${indexName ?? INDEX_PLACEHOLDER}", + mappings: { + properties: { + text: { type: "text"} + }, + }, });`, }, dense_vector: { - installCommand: SERVERLESS_INSTALL_CMD, + installCommand: INSTALL_CMD, createIndex: ({ elasticsearchURL, apiKey, @@ -64,12 +69,36 @@ client.indices.create({ text: { type: "text"} }, }, +});`, + }, + semantic: { + installCommand: INSTALL_CMD, + createIndex: ({ + elasticsearchURL, + apiKey, + indexName, + }) => `import { Client } from "@elastic/elasticsearch" + +const client = new Client({ + node: '${elasticsearchURL}', + auth: { + apiKey: "${apiKey ?? API_KEY_PLACEHOLDER}" + } +}); + +client.indices.create({ + index: "${indexName ?? INDEX_PLACEHOLDER}", + mappings: { + properties: { + text: { type: "semantic_text"} + }, + }, });`, }, }; -export const JSServerlessIngestVectorDataExample: IngestDataCodeDefinition = { - installCommand: SERVERLESS_INSTALL_CMD, +export const JSIngestDataExample: IngestDataCodeDefinition = { + installCommand: INSTALL_CMD, ingestCommand: ({ apiKey, elasticsearchURL, diff --git a/x-pack/solutions/search/plugins/search_indices/public/code_examples/python.ts b/x-pack/solutions/search/plugins/search_indices/public/code_examples/python.ts index cf2b06603c381..326e3259663be 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/code_examples/python.ts +++ b/x-pack/solutions/search/plugins/search_indices/public/code_examples/python.ts @@ -23,11 +23,11 @@ export const PYTHON_INFO: CodeLanguage = { codeBlockLanguage: 'python', }; -const SERVERLESS_PYTHON_INSTALL_CMD = 'pip install elasticsearch'; +const PYTHON_INSTALL_CMD = 'pip install elasticsearch'; -export const PythonServerlessCreateIndexExamples: CreateIndexLanguageExamples = { +export const PythonCreateIndexExamples: CreateIndexLanguageExamples = { default: { - installCommand: SERVERLESS_PYTHON_INSTALL_CMD, + installCommand: PYTHON_INSTALL_CMD, createIndex: ({ elasticsearchURL, apiKey, @@ -40,11 +40,16 @@ client = Elasticsearch( ) client.indices.create( - index="${indexName ?? INDEX_PLACEHOLDER}" + index="${indexName ?? INDEX_PLACEHOLDER}", + mappings={ + "properties": { + "text": {"type": "text"} + } + } )`, }, dense_vector: { - installCommand: SERVERLESS_PYTHON_INSTALL_CMD, + installCommand: PYTHON_INSTALL_CMD, createIndex: ({ elasticsearchURL, apiKey, @@ -64,10 +69,32 @@ client.indices.create( "text": {"type": "text"} } } +)`, + }, + semantic: { + installCommand: PYTHON_INSTALL_CMD, + createIndex: ({ + elasticsearchURL, + apiKey, + indexName, + }: CodeSnippetParameters) => `from elasticsearch import Elasticsearch + +client = Elasticsearch( + "${elasticsearchURL}", + api_key="${apiKey ?? API_KEY_PLACEHOLDER}" +) + +client.indices.create( + index="${indexName ?? INDEX_PLACEHOLDER}", + mappings={ + "properties": { + "text": {"type": "semantic_text"} + } + } )`, }, }; -const serverlessIngestionCommand: IngestCodeSnippetFunction = ({ +const ingestionCommand: IngestCodeSnippetFunction = ({ elasticsearchURL, apiKey, indexName, @@ -86,7 +113,7 @@ docs = ${JSON.stringify(sampleDocuments, null, 4)} bulk_response = helpers.bulk(client, docs, index=index_name) print(bulk_response)`; -const serverlessUpdateMappingsCommand: IngestCodeSnippetFunction = ({ +const updateMappingsCommand: IngestCodeSnippetFunction = ({ elasticsearchURL, apiKey, indexName, @@ -106,8 +133,8 @@ mapping_response = client.indices.put_mapping(index=index_name, body=mappings) print(mapping_response) `; -export const PythonServerlessVectorsIngestDataExample: IngestDataCodeDefinition = { - installCommand: SERVERLESS_PYTHON_INSTALL_CMD, - ingestCommand: serverlessIngestionCommand, - updateMappingsCommand: serverlessUpdateMappingsCommand, +export const PythonIngestDataExample: IngestDataCodeDefinition = { + installCommand: PYTHON_INSTALL_CMD, + ingestCommand: ingestionCommand, + updateMappingsCommand, }; diff --git a/x-pack/solutions/search/plugins/search_indices/public/code_examples/sense.ts b/x-pack/solutions/search/plugins/search_indices/public/code_examples/sense.ts index f54071003df64..8d6a01ff7e34c 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/code_examples/sense.ts +++ b/x-pack/solutions/search/plugins/search_indices/public/code_examples/sense.ts @@ -11,7 +11,16 @@ import { CreateIndexLanguageExamples } from './types'; export const ConsoleCreateIndexExamples: CreateIndexLanguageExamples = { default: { - createIndex: ({ indexName }) => `PUT /${indexName ?? INDEX_PLACEHOLDER}`, + createIndex: ({ indexName }) => `PUT /${indexName ?? INDEX_PLACEHOLDER} +{ + "mappings": { + "properties":{ + "text":{ + "type":"text" + } + } + } +}`, }, dense_vector: { createIndex: ({ indexName }) => `PUT /${indexName ?? INDEX_PLACEHOLDER} @@ -27,11 +36,23 @@ export const ConsoleCreateIndexExamples: CreateIndexLanguageExamples = { } } } +}`, + }, + semantic: { + createIndex: ({ indexName }) => `PUT /${indexName ?? INDEX_PLACEHOLDER} +{ + "mappings": { + "properties":{ + "text":{ + "type":"semantic_text" + } + } + } }`, }, }; -export const ConsoleVectorsIngestDataExample: IngestDataCodeDefinition = { +export const ConsoleIngestDataExample: IngestDataCodeDefinition = { ingestCommand: ({ indexName, sampleDocuments }) => { let result = 'POST /_bulk?pretty\n'; sampleDocuments.forEach((document) => { diff --git a/x-pack/solutions/search/plugins/search_indices/public/code_examples/types.ts b/x-pack/solutions/search/plugins/search_indices/public/code_examples/types.ts index dc8f877f565d5..cc99baae41a8c 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/code_examples/types.ts +++ b/x-pack/solutions/search/plugins/search_indices/public/code_examples/types.ts @@ -10,8 +10,11 @@ import { CreateIndexCodeDefinition, IngestDataCodeDefinition } from '../types'; export interface CreateIndexLanguageExamples { default: CreateIndexCodeDefinition; dense_vector: CreateIndexCodeDefinition; + semantic: CreateIndexCodeDefinition; } export interface IngestDataLanguageExamples { + default: IngestDataCodeDefinition; dense_vector: IngestDataCodeDefinition; + semantic: IngestDataCodeDefinition; } diff --git a/x-pack/solutions/search/plugins/search_indices/public/code_examples/workflows.ts b/x-pack/solutions/search/plugins/search_indices/public/code_examples/workflows.ts new file mode 100644 index 0000000000000..29d2a64254028 --- /dev/null +++ b/x-pack/solutions/search/plugins/search_indices/public/code_examples/workflows.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 { i18n } from '@kbn/i18n'; + +export type WorkflowId = 'default' | 'vector' | 'semantic'; + +export interface Workflow { + title: string; + id: WorkflowId; + summary: string; +} + +export const workflows: Workflow[] = [ + { + title: i18n.translate('xpack.searchIndices.workflows.default', { + defaultMessage: 'Keyword Search', + }), + id: 'default', + summary: i18n.translate('xpack.searchIndices.workflows.defaultSummary', { + defaultMessage: 'Set up an index in Elasticsearch using the text field mapping.', + }), + }, + { + title: i18n.translate('xpack.searchIndices.workflows.vector', { + defaultMessage: 'Vector Search', + }), + id: 'vector', + summary: i18n.translate('xpack.searchIndices.workflows.vectorSummary', { + defaultMessage: 'Set up an index in Elasticsearch using the dense_vector field mapping.', + }), + }, + { + title: i18n.translate('xpack.searchIndices.workflows.semantic', { + defaultMessage: 'Semantic Search', + }), + id: 'semantic', + summary: i18n.translate('xpack.searchIndices.workflows.semanticSummary', { + defaultMessage: + "Semantic search in Elasticsearch is now simpler with the new semantic_text field type. This example walks through setting up your index with a semantic_text field, which uses Elastic's built-in ELSER machine learning model. If the model is not running, a new deployment will start once the mappings are defined.", + }), + }, +]; diff --git a/x-pack/solutions/search/plugins/search_indices/public/components/create_index/create_index.tsx b/x-pack/solutions/search/plugins/search_indices/public/components/create_index/create_index.tsx index f09ae3856c097..2f4081b99d486 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/components/create_index/create_index.tsx +++ b/x-pack/solutions/search/plugins/search_indices/public/components/create_index/create_index.tsx @@ -22,6 +22,8 @@ import { CreateIndexPanel } from '../shared/create_index_panel'; import { CreateIndexCodeView } from './create_index_code_view'; import { CreateIndexUIView } from './create_index_ui_view'; +import { WorkflowId } from '../../code_examples/workflows'; +import { useWorkflow } from '../shared/hooks/use_workflow'; function initCreateIndexState() { const defaultIndexName = generateRandomIndexName(); @@ -50,6 +52,7 @@ export const CreateIndex = ({ indicesData }: CreateIndexProps) => { ? CreateIndexViewMode.Code : CreateIndexViewMode.UI ); + const { workflow, setSelectedWorkflowId } = useWorkflow(); const usageTracker = useUsageTracker(); const onChangeView = useCallback( (id: string) => { @@ -102,6 +105,14 @@ export const CreateIndex = ({ indicesData }: CreateIndexProps) => { selectedLanguage={formState.codingLanguage} indexName={formState.indexName} changeCodingLanguage={onChangeCodingLanguage} + changeWorkflowId={(workflowId: WorkflowId) => { + setSelectedWorkflowId(workflowId); + usageTracker.click([ + AnalyticsEvents.startCreateIndexWorkflowSelect, + `${AnalyticsEvents.startCreateIndexWorkflowSelect}_${workflowId}`, + ]); + }} + selectedWorkflow={workflow} canCreateApiKey={userPrivileges?.privileges.canCreateApiKeys} analyticsEvents={{ runInConsole: AnalyticsEvents.createIndexRunInConsole, diff --git a/x-pack/solutions/search/plugins/search_indices/public/components/index_documents/add_documents_code_example.test.tsx b/x-pack/solutions/search/plugins/search_indices/public/components/index_documents/add_documents_code_example.test.tsx index c5fdc7428e690..e19ece4162dcb 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/components/index_documents/add_documents_code_example.test.tsx +++ b/x-pack/solutions/search/plugins/search_indices/public/components/index_documents/add_documents_code_example.test.tsx @@ -7,11 +7,7 @@ import React from 'react'; import { render } from '@testing-library/react'; -import { - AddDocumentsCodeExample, - basicExampleTexts, - exampleTextsWithCustomMapping, -} from './add_documents_code_example'; +import { AddDocumentsCodeExample, exampleTexts } from './add_documents_code_example'; import { generateSampleDocument } from '../../utils/document_generation'; import { MappingProperty } from '@elastic/elasticsearch/lib/api/types'; @@ -71,7 +67,7 @@ describe('AddDocumentsCodeExample', () => { expect(generateSampleDocument).toHaveBeenCalledTimes(3); - basicExampleTexts.forEach((text, index) => { + exampleTexts.forEach((text, index) => { expect(generateSampleDocument).toHaveBeenNthCalledWith(index + 1, mappingProperties, text); }); }); @@ -84,16 +80,15 @@ describe('AddDocumentsCodeExample', () => { expect(generateSampleDocument).toHaveBeenCalledTimes(3); const mappingProperties: Record = { - vector: { type: 'dense_vector', dims: 3 }, text: { type: 'text' }, }; - basicExampleTexts.forEach((text, index) => { + exampleTexts.forEach((text, index) => { expect(generateSampleDocument).toHaveBeenNthCalledWith(index + 1, mappingProperties, text); }); }); - it('pass basic examples when mapping is default with extra vector fields', () => { + it('pass examples when mapping is default with extra vector fields', () => { const indexName = 'test-index'; const mappingProperties: Record = { vector: { type: 'dense_vector', dims: 3, similarity: 'extra' }, @@ -106,25 +101,7 @@ describe('AddDocumentsCodeExample', () => { expect(generateSampleDocument).toHaveBeenCalledTimes(3); - basicExampleTexts.forEach((text, index) => { - expect(generateSampleDocument).toHaveBeenNthCalledWith(index + 1, mappingProperties, text); - }); - }); - - it('pass examples text when mapping is custom', () => { - const indexName = 'test-index'; - const mappingProperties: Record = { - text: { type: 'text' }, - test: { type: 'boolean' }, - }; - - render( - - ); - - expect(generateSampleDocument).toHaveBeenCalledTimes(3); - - exampleTextsWithCustomMapping.forEach((text, index) => { + exampleTexts.forEach((text, index) => { expect(generateSampleDocument).toHaveBeenNthCalledWith(index + 1, mappingProperties, text); }); }); diff --git a/x-pack/solutions/search/plugins/search_indices/public/components/index_documents/add_documents_code_example.tsx b/x-pack/solutions/search/plugins/search_indices/public/components/index_documents/add_documents_code_example.tsx index d96055b5dc184..e4655f6a858b5 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/components/index_documents/add_documents_code_example.tsx +++ b/x-pack/solutions/search/plugins/search_indices/public/components/index_documents/add_documents_code_example.tsx @@ -6,17 +6,15 @@ */ import React, { useCallback, useMemo, useState } from 'react'; -import { MappingDenseVectorProperty, MappingProperty } from '@elastic/elasticsearch/lib/api/types'; -import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui'; +import { MappingProperty } from '@elastic/elasticsearch/lib/api/types'; +import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { TryInConsoleButton } from '@kbn/try-in-console'; -import { isEqual } from 'lodash'; import { useSearchApiKey } from '@kbn/search-api-keys-components'; import { useKibana } from '../../hooks/use_kibana'; import { IngestCodeSnippetParameters } from '../../types'; import { LanguageSelector } from '../shared/language_selector'; -import { useIngestCodeExamples } from './hooks/use_ingest_code_examples'; import { useElasticsearchUrl } from '../../hooks/use_elasticsearch_url'; import { useUsageTracker } from '../../contexts/usage_tracker_context'; import { AvailableLanguages, LanguageOptions, Languages } from '../../code_examples'; @@ -24,13 +22,15 @@ import { AnalyticsEvents } from '../../analytics/constants'; import { CodeSample } from '../shared/code_sample'; import { generateSampleDocument } from '../../utils/document_generation'; import { getDefaultCodingLanguage } from '../../utils/language'; +import { GuideSelector } from '../shared/guide_selector'; +import { useWorkflow } from '../shared/hooks/use_workflow'; +import { WorkflowId } from '../../code_examples/workflows'; -export const basicExampleTexts = [ - 'Yellowstone National Park', - 'Yosemite National Park', - 'Rocky Mountain National Park', +export const exampleTexts = [ + 'Yellowstone National Park is one of the largest national parks in the United States. It ranges from the Wyoming to Montana and Idaho, and contains an area of 2,219,791 acress across three different states. Its most famous for hosting the geyser Old Faithful and is centered on the Yellowstone Caldera, the largest super volcano on the American continent. Yellowstone is host to hundreds of species of animal, many of which are endangered or threatened. Most notably, it contains free-ranging herds of bison and elk, alongside bears, cougars and wolves. The national park receives over 4.5 million visitors annually and is a UNESCO World Heritage Site.', + 'Yosemite National Park is a United States National Park, covering over 750,000 acres of land in California. A UNESCO World Heritage Site, the park is best known for its granite cliffs, waterfalls and giant sequoia trees. Yosemite hosts over four million visitors in most years, with a peak of five million visitors in 2016. The park is home to a diverse range of wildlife, including mule deer, black bears, and the endangered Sierra Nevada bighorn sheep. The park has 1,200 square miles of wilderness, and is a popular destination for rock climbers, with over 3,000 feet of vertical granite to climb. Its most famous and cliff is the El Capitan, a 3,000 feet monolith along its tallest face.', + 'Rocky Mountain National Park is one of the most popular national parks in the United States. It receives over 4.5 million visitors annually, and is known for its mountainous terrain, including Longs Peak, which is the highest peak in the park. The park is home to a variety of wildlife, including elk, mule deer, moose, and bighorn sheep. The park is also home to a variety of ecosystems, including montane, subalpine, and alpine tundra. The park is a popular destination for hiking, camping, and wildlife viewing, and is a UNESCO World Heritage Site.', ]; -export const exampleTextsWithCustomMapping = [1, 2, 3].map((num) => `Example text ${num}`); export interface AddDocumentsCodeExampleProps { indexName: string; @@ -42,41 +42,28 @@ export const AddDocumentsCodeExample = ({ mappingProperties, }: AddDocumentsCodeExampleProps) => { const { application, share, console: consolePlugin } = useKibana().services; - const ingestCodeExamples = useIngestCodeExamples(); const elasticsearchUrl = useElasticsearchUrl(); const usageTracker = useUsageTracker(); const indexHasMappings = Object.keys(mappingProperties).length > 0; const [selectedLanguage, setSelectedLanguage] = useState(getDefaultCodingLanguage); - const selectedCodeExamples = ingestCodeExamples[selectedLanguage]; - const codeSampleMappings = indexHasMappings - ? mappingProperties - : ingestCodeExamples.defaultMapping; + const { selectedWorkflowId, setSelectedWorkflowId, ingestExamples, workflow } = useWorkflow(); + const selectedCodeExamples = ingestExamples[selectedLanguage]; + const codeSampleMappings = indexHasMappings ? mappingProperties : ingestExamples.defaultMapping; const onSelectLanguage = useCallback( (value: AvailableLanguages) => { setSelectedLanguage(value); usageTracker.count([ - AnalyticsEvents.startCreateIndexLanguageSelect, - `${AnalyticsEvents.startCreateIndexLanguageSelect}_${value}`, + AnalyticsEvents.indexDetailsCodeLanguageSelect, + `${AnalyticsEvents.indexDetailsCodeLanguageSelect}_${value}`, ]); }, [usageTracker] ); const sampleDocuments = useMemo(() => { - // If the default mapping was used, we need to exclude generated vector fields - const copyCodeSampleMappings = { - ...codeSampleMappings, - vector: { - type: codeSampleMappings.vector?.type, - dims: (codeSampleMappings.vector as MappingDenseVectorProperty)?.dims, - }, - }; - const isDefaultMapping = isEqual(copyCodeSampleMappings, ingestCodeExamples.defaultMapping); - const sampleTexts = isDefaultMapping ? basicExampleTexts : exampleTextsWithCustomMapping; - - return sampleTexts.map((text) => generateSampleDocument(codeSampleMappings, text)); - }, [codeSampleMappings, ingestCodeExamples.defaultMapping]); + return exampleTexts.map((text) => generateSampleDocument(codeSampleMappings, text)); + }, [codeSampleMappings]); const { apiKey } = useSearchApiKey(); const codeParams: IngestCodeSnippetParameters = useMemo(() => { return { @@ -88,6 +75,7 @@ export const AddDocumentsCodeExample = ({ apiKey: apiKey || undefined, }; }, [indexName, elasticsearchUrl, sampleDocuments, codeSampleMappings, indexHasMappings, apiKey]); + const [panelRef, setPanelRef] = useState(null); return ( - - - + {!indexHasMappings && ( + + { + setSelectedWorkflowId(workflowId); + usageTracker.click([ + AnalyticsEvents.indexDetailsCodeLanguageSelect, + `${AnalyticsEvents.indexDetailsCodeLanguageSelect}_${workflowId}`, + ]); + }} + showTour + container={panelRef} + /> + + )} + {!!workflow && ( + + +

{workflow.title}

+
+ + +

{workflow.summary}

+
+
+ )} + + + {selectedCodeExamples.installCommand && ( { @@ -141,8 +158,8 @@ export const AddDocumentsCodeExample = ({ { diff --git a/x-pack/solutions/search/plugins/search_indices/public/components/index_documents/hooks/use_ingest_code_examples.tsx b/x-pack/solutions/search/plugins/search_indices/public/components/index_documents/hooks/use_ingest_code_examples.tsx deleted file mode 100644 index 7eb84e6f62933..0000000000000 --- a/x-pack/solutions/search/plugins/search_indices/public/components/index_documents/hooks/use_ingest_code_examples.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import * as IngestCodeExamples from '../../../code_examples/ingest_data'; - -export const useIngestCodeExamples = () => { - // TODO: Choose code examples based on onboarding token, stack vs es3, or project type - return IngestCodeExamples.DenseVectorServerlessCodeExamples; -}; diff --git a/x-pack/solutions/search/plugins/search_indices/public/components/indices/details_page.tsx b/x-pack/solutions/search/plugins/search_indices/public/components/indices/details_page.tsx index e7d9eb96bb660..16b355955c2b2 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/components/indices/details_page.tsx +++ b/x-pack/solutions/search/plugins/search_indices/public/components/indices/details_page.tsx @@ -79,12 +79,7 @@ export const SearchIndexDetailsPage = () => { }, [share, index]); const navigateToDiscover = useNavigateToDiscover(indexName); - const [hasDocuments, setHasDocuments] = useState(false); - const [isDocumentsLoading, setDocumentsLoading] = useState(true); - useEffect(() => { - setDocumentsLoading(isInitialLoading); - setHasDocuments(!(!isInitialLoading && indexDocuments?.results?.data.length === 0)); - }, [indexDocuments, isInitialLoading, setHasDocuments, setDocumentsLoading]); + const hasDocuments = Boolean(isInitialLoading || indexDocuments?.results?.data.length); usePageChrome(indexName, [ ...IndexManagementBreadcrumbs, @@ -225,7 +220,7 @@ export const SearchIndexDetailsPage = () => { <> @@ -237,7 +232,7 @@ export const SearchIndexDetailsPage = () => { { diff --git a/x-pack/solutions/search/plugins/search_indices/public/components/shared/create_index_code_view.tsx b/x-pack/solutions/search/plugins/search_indices/public/components/shared/create_index_code_view.tsx index c169179bf2982..389e5dcd0b989 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/components/shared/create_index_code_view.tsx +++ b/x-pack/solutions/search/plugins/search_indices/public/components/shared/create_index_code_view.tsx @@ -5,7 +5,7 @@ * 2.0. */ import React, { useMemo } from 'react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; import { TryInConsoleButton } from '@kbn/try-in-console'; import { useSearchApiKey } from '@kbn/search-api-keys-components'; @@ -17,13 +17,17 @@ import { useElasticsearchUrl } from '../../hooks/use_elasticsearch_url'; import { APIKeyCallout } from './api_key_callout'; import { CodeSample } from './code_sample'; -import { useCreateIndexCodingExamples } from './hooks/use_create_index_coding_examples'; +import { useWorkflow } from './hooks/use_workflow'; import { LanguageSelector } from './language_selector'; +import { GuideSelector } from './guide_selector'; +import { Workflow, WorkflowId } from '../../code_examples/workflows'; export interface CreateIndexCodeViewProps { selectedLanguage: AvailableLanguages; indexName: string; changeCodingLanguage: (language: AvailableLanguages) => void; + changeWorkflowId: (workflowId: WorkflowId) => void; + selectedWorkflow?: Workflow; canCreateApiKey?: boolean; analyticsEvents: { runInConsole: string; @@ -36,12 +40,14 @@ export const CreateIndexCodeView = ({ analyticsEvents, canCreateApiKey, changeCodingLanguage, + changeWorkflowId, + selectedWorkflow, indexName, selectedLanguage, }: CreateIndexCodeViewProps) => { const { application, share, console: consolePlugin } = useKibana().services; const usageTracker = useUsageTracker(); - const selectedCodeExamples = useCreateIndexCodingExamples(); + const { createIndexExamples: selectedCodeExamples } = useWorkflow(); const elasticsearchUrl = useElasticsearchUrl(); const { apiKey } = useSearchApiKey(); @@ -64,30 +70,52 @@ export const CreateIndexCodeView = ({ )} - - - - - - { - usageTracker.click([ - analyticsEvents.runInConsole, - `${analyticsEvents.runInConsole}_${selectedLanguage}`, - ]); - }} - /> - - + + + + + + + { + usageTracker.click([ + analyticsEvents.runInConsole, + `${analyticsEvents.runInConsole}_${selectedLanguage}`, + ]); + }} + /> + + + + {!!selectedWorkflow && ( + <> + + +

{selectedWorkflow?.title}

+
+ + +

{selectedWorkflow?.summary}

+
+
+ + )} + + + {selectedCodeExample.installCommand && ( void; +} + +const PopoverCard: React.FC = ({ workflow, onChange, isSelected }) => ( + + {workflow.summary} + + } + selectable={{ + onClick: () => onChange(workflow.id), + isSelected, + }} + /> +); + +interface GuideSelectorProps { + selectedWorkflowId: WorkflowId; + onChange: (workflow: WorkflowId) => void; + showTour: boolean; + container?: HTMLElement | null; +} + +export const GuideSelector: React.FC = ({ + selectedWorkflowId, + onChange, + showTour, + container, +}) => { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const { tourIsOpen, setTourIsOpen } = useGuideTour(); + + const onPopoverClick = () => { + setIsPopoverOpen(() => !isPopoverOpen); + }; + + useEffect(() => { + closePopover(); + }, [selectedWorkflowId]); + + const closePopover = () => setIsPopoverOpen(false); + + const PopoverButton = ( + + {i18n.translate('xpack.searchIndices.guideSelector.selectWorkflow', { + defaultMessage: 'Select a guide', + })} + + ); + + const Popover = () => ( + + <> + + {workflows.map((workflow) => ( + + onChange(value)} + /> + + ))} + + + + ); + + return showTour ? ( + +

+ {i18n.translate('xpack.searchIndices.tourDescription', { + defaultMessage: 'Explore additional guides for setting up your Elasticsearch index.', + })} +

+ + } + isStepOpen={tourIsOpen} + minWidth={300} + onFinish={() => setTourIsOpen(false)} + step={1} + stepsTotal={1} + title={i18n.translate('xpack.searchIndices.touTitle', { + defaultMessage: 'New guides available!', + })} + anchorPosition="rightUp" + > + +
+ ) : ( + + ); +}; diff --git a/x-pack/solutions/search/plugins/search_indices/public/components/shared/hooks/use_create_index_coding_examples.tsx b/x-pack/solutions/search/plugins/search_indices/public/components/shared/hooks/use_create_index_coding_examples.tsx deleted file mode 100644 index fb1cb6a7eab52..0000000000000 --- a/x-pack/solutions/search/plugins/search_indices/public/components/shared/hooks/use_create_index_coding_examples.tsx +++ /dev/null @@ -1,15 +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 { CreateIndexCodeExamples } from '../../../types'; -import { DenseVectorSeverlessCodeExamples } from '../../../code_examples/create_index'; - -export const useCreateIndexCodingExamples = (): CreateIndexCodeExamples => { - // TODO: in the future this will be dynamic based on the onboarding token - // or project sub-type - return DenseVectorSeverlessCodeExamples; -}; diff --git a/x-pack/solutions/search/plugins/search_indices/public/components/shared/hooks/use_guide_tour.tsx b/x-pack/solutions/search/plugins/search_indices/public/components/shared/hooks/use_guide_tour.tsx new file mode 100644 index 0000000000000..fee2fc156a914 --- /dev/null +++ b/x-pack/solutions/search/plugins/search_indices/public/components/shared/hooks/use_guide_tour.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 { useState } from 'react'; + +const GUIDE_TOUR_KEY = 'searchIndicesIngestDataGuideTour'; + +export const useGuideTour = () => { + const hasDismissedGuide = localStorage.getItem(GUIDE_TOUR_KEY) === 'dismissed'; + const [tourIsOpen, setTourIsOpen] = useState(!hasDismissedGuide); + return { + tourIsOpen, + setTourIsOpen: (isOpen: boolean) => { + setTourIsOpen(isOpen); + localStorage.setItem(GUIDE_TOUR_KEY, isOpen ? '' : 'dismissed'); + }, + }; +}; diff --git a/x-pack/solutions/search/plugins/search_indices/public/components/shared/hooks/use_workflow.tsx b/x-pack/solutions/search/plugins/search_indices/public/components/shared/hooks/use_workflow.tsx new file mode 100644 index 0000000000000..0db49738aed8d --- /dev/null +++ b/x-pack/solutions/search/plugins/search_indices/public/components/shared/hooks/use_workflow.tsx @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useState } from 'react'; +import { + DenseVectorIngestDataCodeExamples, + SemanticIngestDataCodeExamples, + DefaultIngestDataCodeExamples, +} from '../../../code_examples/ingest_data'; +import { WorkflowId, workflows } from '../../../code_examples/workflows'; +import { + DefaultCodeExamples, + DenseVectorCodeExamples, + SemanticCodeExamples, +} from '../../../code_examples/create_index'; + +const workflowIdToCreateIndexExamples = (type: WorkflowId) => { + switch (type) { + case 'vector': + return DenseVectorCodeExamples; + case 'semantic': + return SemanticCodeExamples; + default: + return DefaultCodeExamples; + } +}; + +const workflowIdToIngestDataExamples = (type: WorkflowId) => { + switch (type) { + case 'vector': + return DenseVectorIngestDataCodeExamples; + case 'semantic': + return SemanticIngestDataCodeExamples; + default: + return DefaultIngestDataCodeExamples; + } +}; + +export const useWorkflow = () => { + // TODO: in the future this will be dynamic based on the onboarding token + // or project sub-type + const [selectedWorkflowId, setSelectedWorkflowId] = useState('default'); + return { + selectedWorkflowId, + setSelectedWorkflowId, + workflow: workflows.find((workflow) => workflow.id === selectedWorkflowId), + createIndexExamples: workflowIdToCreateIndexExamples(selectedWorkflowId), + ingestExamples: workflowIdToIngestDataExamples(selectedWorkflowId), + }; +}; diff --git a/x-pack/solutions/search/plugins/search_indices/public/components/shared/language_selector.tsx b/x-pack/solutions/search/plugins/search_indices/public/components/shared/language_selector.tsx index ce31e4c38e0fe..406b658cb181d 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/components/shared/language_selector.tsx +++ b/x-pack/solutions/search/plugins/search_indices/public/components/shared/language_selector.tsx @@ -17,12 +17,14 @@ export interface LanguageSelectorProps { selectedLanguage: AvailableLanguages; options: CodeLanguage[]; onSelectLanguage: (value: AvailableLanguages) => void; + showLabel?: boolean; } export const LanguageSelector = ({ selectedLanguage, options, onSelectLanguage, + showLabel = false, }: LanguageSelectorProps) => { const assetBasePath = useAssetBasePath(); const languageOptions = useMemo( @@ -48,6 +50,16 @@ export const LanguageSelector = ({ ); return ( + prepend={ + showLabel + ? i18n.translate('xpack.searchIndices.codeLanguage.selectLabel', { + defaultMessage: 'Language', + }) + : undefined + } + aria-label={i18n.translate('xpack.searchIndices.codeLanguage.selectLabel', { + defaultMessage: 'Select a programming language for the code examples', + })} options={languageOptions} valueOfSelected={selectedLanguage} onChange={(value) => onSelectLanguage(value)} diff --git a/x-pack/solutions/search/plugins/search_indices/public/components/start/elasticsearch_start.tsx b/x-pack/solutions/search/plugins/search_indices/public/components/start/elasticsearch_start.tsx index 7b525250ff493..0b359688353a5 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/components/start/elasticsearch_start.tsx +++ b/x-pack/solutions/search/plugins/search_indices/public/components/start/elasticsearch_start.tsx @@ -23,6 +23,8 @@ import { CreateIndexFormState, CreateIndexViewMode } from '../../types'; import { CreateIndexPanel } from '../shared/create_index_panel'; import { useKibana } from '../../hooks/use_kibana'; import { useUserPrivilegesQuery } from '../../hooks/api/use_user_permissions'; +import { WorkflowId } from '../../code_examples/workflows'; +import { useWorkflow } from '../shared/hooks/use_workflow'; function initCreateIndexState(): CreateIndexFormState { const defaultIndexName = generateRandomIndexName(); @@ -48,6 +50,7 @@ export const ElasticsearchStart: React.FC = () => { : CreateIndexViewMode.UI ); const usageTracker = useUsageTracker(); + const { workflow, setSelectedWorkflowId } = useWorkflow(); useEffect(() => { usageTracker.load(AnalyticsEvents.startPageOpened); @@ -114,6 +117,14 @@ export const ElasticsearchStart: React.FC = () => { selectedLanguage={formState.codingLanguage} indexName={formState.indexName} changeCodingLanguage={onChangeCodingLanguage} + changeWorkflowId={(workflowId: WorkflowId) => { + setSelectedWorkflowId(workflowId); + usageTracker.click([ + AnalyticsEvents.startCreateIndexWorkflowSelect, + `${AnalyticsEvents.startCreateIndexWorkflowSelect}_${workflowId}`, + ]); + }} + selectedWorkflow={workflow} canCreateApiKey={userPrivileges?.privileges.canCreateApiKeys} analyticsEvents={{ runInConsole: AnalyticsEvents.startCreateIndexRunInConsole, diff --git a/x-pack/solutions/search/plugins/search_indices/public/hooks/api/use_document_search.ts b/x-pack/solutions/search/plugins/search_indices/public/hooks/api/use_document_search.ts index a8afd69385623..db0e9bac718c8 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/hooks/api/use_document_search.ts +++ b/x-pack/solutions/search/plugins/search_indices/public/hooks/api/use_document_search.ts @@ -27,7 +27,7 @@ export const useIndexDocumentSearch = (indexName: string) => { const { services: { http }, } = useKibana(); - const response = useQuery({ + const { data, isInitialLoading } = useQuery({ queryKey: [QueryKeys.SearchDocuments, indexName], refetchInterval: INDEX_SEARCH_POLLING, refetchIntervalInBackground: true, @@ -46,7 +46,8 @@ export const useIndexDocumentSearch = (indexName: string) => { }), }); return { - ...response, - meta: pageToPagination(response?.data?.results?._meta?.page ?? DEFAULT_PAGINATION), + data, + isInitialLoading, + meta: pageToPagination(data?.results?._meta?.page ?? DEFAULT_PAGINATION), }; }; diff --git a/x-pack/solutions/search/plugins/search_indices/public/hooks/api/use_index.ts b/x-pack/solutions/search/plugins/search_indices/public/hooks/api/use_index.ts index e91e4c9d06f5f..1f0ad428a33b9 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/hooks/api/use_index.ts +++ b/x-pack/solutions/search/plugins/search_indices/public/hooks/api/use_index.ts @@ -14,7 +14,7 @@ const POLLING_INTERVAL = 15 * 1000; export const useIndex = (indexName: string) => { const { http } = useKibana().services; const queryKey = [QueryKeys.FetchIndex, indexName]; - const result = useQuery({ + return useQuery({ queryKey, refetchInterval: POLLING_INTERVAL, refetchIntervalInBackground: true, @@ -25,5 +25,4 @@ export const useIndex = (indexName: string) => { queryFn: () => http.fetch(`/internal/index_management/indices/${encodeURIComponent(indexName)}`), }); - return { queryKey, ...result }; }; diff --git a/x-pack/solutions/search/plugins/search_indices/public/hooks/api/use_index_mappings.ts b/x-pack/solutions/search/plugins/search_indices/public/hooks/api/use_index_mappings.ts index 1d5a83aa920ed..b09cf79f4aba4 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/hooks/api/use_index_mappings.ts +++ b/x-pack/solutions/search/plugins/search_indices/public/hooks/api/use_index_mappings.ts @@ -14,7 +14,7 @@ const POLLING_INTERVAL = 15 * 1000; export const useIndexMapping = (indexName: string) => { const { http } = useKibana().services; const queryKey = [QueryKeys.FetchMapping, indexName]; - const result = useQuery({ + return useQuery({ queryKey, refetchInterval: POLLING_INTERVAL, refetchIntervalInBackground: true, @@ -22,5 +22,4 @@ export const useIndexMapping = (indexName: string) => { queryFn: () => http.fetch(`/api/index_management/mapping/${encodeURIComponent(indexName)}`), }); - return { queryKey, ...result }; }; diff --git a/x-pack/solutions/search/plugins/search_playground/__mocks__/fetch_query_source_fields.mock.ts b/x-pack/solutions/search/plugins/search_playground/__mocks__/fetch_query_source_fields.mock.ts index 7ab5f261989a4..7ba2cef9b2b34 100644 --- a/x-pack/solutions/search/plugins/search_playground/__mocks__/fetch_query_source_fields.mock.ts +++ b/x-pack/solutions/search/plugins/search_playground/__mocks__/fetch_query_source_fields.mock.ts @@ -11,10 +11,10 @@ export const SPARSE_SEMANTIC_FIELD_FIELD_CAPS = { indices: ['test-index2'], fields: { infer_field: { - semantic_text: { - type: 'semantic_text', + text: { + type: 'text', metadata_field: false, - searchable: false, + searchable: true, aggregatable: false, }, }, @@ -127,10 +127,10 @@ export const DENSE_SEMANTIC_FIELD_FIELD_CAPS = { indices: ['test-index2'], fields: { infer_field: { - semantic_text: { - type: 'semantic_text', + text: { + type: 'text', metadata_field: false, - searchable: false, + searchable: true, aggregatable: false, }, }, diff --git a/x-pack/solutions/search/plugins/search_playground/public/components/view_code/examples/__snapshots__/py_lang_client.test.tsx.snap b/x-pack/solutions/search/plugins/search_playground/public/components/view_code/examples/__snapshots__/py_lang_client.test.tsx.snap index 0001f45600ec2..7944e0ecc188a 100644 --- a/x-pack/solutions/search/plugins/search_playground/public/components/view_code/examples/__snapshots__/py_lang_client.test.tsx.snap +++ b/x-pack/solutions/search/plugins/search_playground/public/components/view_code/examples/__snapshots__/py_lang_client.test.tsx.snap @@ -40,11 +40,12 @@ def get_elasticsearch_results(): def create_openai_prompt(results): context = \\"\\" for hit in results: - inner_hit_path = f\\"{hit['_index']}.{index_source_fields.get(hit['_index'])[0]}\\" - - ## For semantic_text matches, we need to extract the text from the inner_hits - if 'inner_hits' in hit and inner_hit_path in hit['inner_hits']: - context += '\\\\n --- \\\\n'.join(inner_hit['_source']['text'] for inner_hit in hit['inner_hits'][inner_hit_path]['hits']['hits']) + ## For semantic_text matches, we need to extract the text from the highlighted field + if \\"highlight\\" in hit: + highlighted_texts = [] + for values in hit[\\"highlight\\"].values(): + highlighted_texts.extend(values) + context += \\"\\\\n --- \\\\n\\".join(highlighted_texts) else: source_field = index_source_fields.get(hit[\\"_index\\"])[0] hit_context = hit[\\"_source\\"][source_field] diff --git a/x-pack/solutions/search/plugins/search_playground/public/components/view_code/examples/py_lang_client.tsx b/x-pack/solutions/search/plugins/search_playground/public/components/view_code/examples/py_lang_client.tsx index a2d92583c6b63..746ecd293ad5e 100644 --- a/x-pack/solutions/search/plugins/search_playground/public/components/view_code/examples/py_lang_client.tsx +++ b/x-pack/solutions/search/plugins/search_playground/public/components/view_code/examples/py_lang_client.tsx @@ -40,11 +40,12 @@ def get_elasticsearch_results(): def create_openai_prompt(results): context = "" for hit in results: - inner_hit_path = f"{hit['_index']}.{index_source_fields.get(hit['_index'])[0]}" - - ## For semantic_text matches, we need to extract the text from the inner_hits - if 'inner_hits' in hit and inner_hit_path in hit['inner_hits']: - context += '\\n --- \\n'.join(inner_hit['_source']['text'] for inner_hit in hit['inner_hits'][inner_hit_path]['hits']['hits']) + ## For semantic_text matches, we need to extract the text from the highlighted field + if "highlight" in hit: + highlighted_texts = [] + for values in hit["highlight"].values(): + highlighted_texts.extend(values) + context += "\\n --- \\n".join(highlighted_texts) else: source_field = index_source_fields.get(hit["_index"])[0] hit_context = hit["_source"][source_field] diff --git a/x-pack/solutions/search/plugins/search_playground/public/utils/create_query.test.ts b/x-pack/solutions/search/plugins/search_playground/public/utils/create_query.test.ts index c4c986e7b06e6..d6001dd1f2224 100644 --- a/x-pack/solutions/search/plugins/search_playground/public/utils/create_query.test.ts +++ b/x-pack/solutions/search/plugins/search_playground/public/utils/create_query.test.ts @@ -516,20 +516,9 @@ describe('create_query', () => { { standard: { query: { - nested: { - inner_hits: { - _source: ['field2.inference.chunks.text'], - name: 'index1.field2', - size: 2, - }, - path: 'field2.inference.chunks', - query: { - sparse_vector: { - field: 'field2.inference.chunks.embeddings', - inference_id: 'model2', - query: '{query}', - }, - }, + semantic: { + field: 'field2', + query: '{query}', }, }, }, @@ -542,6 +531,15 @@ describe('create_query', () => { ], }, }, + highlight: { + fields: { + field2: { + number_of_fragments: 2, + order: 'score', + type: 'semantic', + }, + }, + }, }); }); @@ -638,24 +636,9 @@ describe('create_query', () => { { standard: { query: { - nested: { - inner_hits: { - _source: ['field2.inference.chunks.text'], - name: 'index1.field2', - size: 2, - }, - path: 'field2.inference.chunks', - query: { - knn: { - field: 'field2.inference.chunks.embeddings', - query_vector_builder: { - text_embedding: { - model_id: 'model2', - model_text: '{query}', - }, - }, - }, - }, + semantic: { + field: 'field2', + query: '{query}', }, }, }, @@ -668,6 +651,15 @@ describe('create_query', () => { ], }, }, + highlight: { + fields: { + field2: { + number_of_fragments: 2, + order: 'score', + type: 'semantic', + }, + }, + }, }); }); diff --git a/x-pack/solutions/search/plugins/search_playground/public/utils/create_query.ts b/x-pack/solutions/search/plugins/search_playground/public/utils/create_query.ts index 63cdcdf76bb65..cf0a1846bfb65 100644 --- a/x-pack/solutions/search/plugins/search_playground/public/utils/create_query.ts +++ b/x-pack/solutions/search/plugins/search_playground/public/utils/create_query.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { RetrieverContainer } from '@elastic/elasticsearch/lib/api/types'; +import { RetrieverContainer, SearchHighlight } from '@elastic/elasticsearch/lib/api/types'; import { IndicesQuerySourceFields, QuerySourceFields } from '../types'; export type IndexFields = Record; @@ -36,6 +36,8 @@ const SUGGESTED_SOURCE_FIELDS = [ 'text_field', ]; +const SEMANTIC_FIELD_TYPE = 'semantic'; + interface Matches { queryMatches: any[]; knnMatches: any[]; @@ -52,7 +54,7 @@ export function createQuery( rerankOptions: ReRankOptions = { rrf: true, } -): { retriever: RetrieverContainer } { +): { retriever: RetrieverContainer; highlight?: SearchHighlight } { const indices = Object.keys(fieldDescriptors); const boolMatches = Object.keys(fields).reduce( (acc, index) => { @@ -64,60 +66,8 @@ export function createQuery( const semanticMatches = indexFields.map((field) => { const semanticField = indexFieldDescriptors.semantic_fields.find((x) => x.field === field); - const isSourceField = sourceFields[index].includes(field); - - // this is needed to get the inner_hits for the source field - // we cant rely on only the semantic field - // in future inner_hits option will be added to semantic - if (semanticField && isSourceField) { - if (semanticField.embeddingType === 'dense_vector') { - const filter = - semanticField.indices.length < indices.length - ? { filter: { terms: { _index: semanticField.indices } } } - : {}; - return { - nested: { - path: `${semanticField.field}.inference.chunks`, - query: { - knn: { - field: `${semanticField.field}.inference.chunks.embeddings`, - ...filter, - query_vector_builder: { - text_embedding: { - model_id: semanticField.inferenceId, - model_text: '{query}', - }, - }, - }, - }, - inner_hits: { - size: 2, - name: `${index}.${semanticField.field}`, - _source: [`${semanticField.field}.inference.chunks.text`], - }, - }, - }; - } else if (semanticField.embeddingType === 'sparse_vector') { - return { - nested: { - path: `${semanticField.field}.inference.chunks`, - query: { - sparse_vector: { - inference_id: semanticField.inferenceId, - field: `${semanticField.field}.inference.chunks.embeddings`, - query: '{query}', - }, - }, - inner_hits: { - size: 2, - name: `${index}.${semanticField.field}`, - _source: [`${semanticField.field}.inference.chunks.text`], - }, - }, - }; - } - } else if (semanticField) { + if (semanticField) { return { semantic: { field: semanticField.field, @@ -241,12 +191,34 @@ export function createQuery( // for single Elser support to make it easy to read - skips bool query if (boolMatches.queryMatches.length === 1 && boolMatches.knnMatches.length === 0) { + const semanticField = boolMatches.queryMatches[0].semantic?.field ?? null; + + let isSourceField = false; + indices.forEach((index) => { + if (sourceFields[index].includes(semanticField)) { + isSourceField = true; + } + }); + return { retriever: { standard: { query: boolMatches.queryMatches[0], }, }, + ...(isSourceField + ? { + highlight: { + fields: { + [semanticField]: { + type: SEMANTIC_FIELD_TYPE, + number_of_fragments: 2, + order: 'score', + }, + }, + }, + } + : {}), }; } @@ -285,12 +257,39 @@ export function createQuery( }; }); + const semanticFields = matches + .filter((match) => match.semantic) + .map((match) => match.semantic.field) + .filter((field) => { + let isSourceField = false; + indices.forEach((index) => { + if (sourceFields[index].includes(field)) { + isSourceField = true; + } + }); + return isSourceField; + }); + return { retriever: { rrf: { retrievers, }, }, + ...(semanticFields.length > 0 + ? { + highlight: { + fields: semanticFields.reduce((acc, field) => { + acc[field] = { + type: SEMANTIC_FIELD_TYPE, + number_of_fragments: 2, + order: 'score', + }; + return acc; + }, {}), + }, + } + : {}), }; } diff --git a/x-pack/solutions/search/plugins/search_playground/server/lib/conversational_chain.test.ts b/x-pack/solutions/search/plugins/search_playground/server/lib/conversational_chain.test.ts index d8958da6ff112..5a59ddead7d9c 100644 --- a/x-pack/solutions/search/plugins/search_playground/server/lib/conversational_chain.test.ts +++ b/x-pack/solutions/search/plugins/search_playground/server/lib/conversational_chain.test.ts @@ -237,19 +237,7 @@ describe('conversational chain', () => { { _index: 'index', _id: '1', - inner_hits: { - 'index.field': { - hits: { - hits: [ - { - _source: { - text: 'value', - }, - }, - ], - }, - }, - }, + highlight: { field: ['value'] }, }, ], expectedDocs: [ diff --git a/x-pack/solutions/search/plugins/search_playground/server/lib/fetch_query_source_fields.ts b/x-pack/solutions/search/plugins/search_playground/server/lib/fetch_query_source_fields.ts index 9592766e115ec..154261a019528 100644 --- a/x-pack/solutions/search/plugins/search_playground/server/lib/fetch_query_source_fields.ts +++ b/x-pack/solutions/search/plugins/search_playground/server/lib/fetch_query_source_fields.ts @@ -244,10 +244,9 @@ export const parseFieldsCapabilities = ( (indexModelIdField) => indexModelIdField.index === index )!; const nestedField = isFieldNested(fieldKey, fieldCapsResponse); + const semanticFieldMapping = getSemanticField(fieldKey, semanticTextFields); - if (isFieldInIndex(field, 'semantic_text', index)) { - const semanticFieldMapping = getSemanticField(fieldKey, semanticTextFields); - + if (isFieldInIndex(field, 'text', index) && semanticFieldMapping) { // only use this when embeddingType and inferenceId is defined // this requires semantic_text field to be set up correctly and ingested if ( @@ -260,7 +259,7 @@ export const parseFieldsCapabilities = ( field: fieldKey, inferenceId: semanticFieldMapping.inferenceId, embeddingType: semanticFieldMapping.embeddingType, - indices: (field.semantic_text.indices as string[]) || indicesPresentIn, + indices: (field.text.indices as string[]) || indicesPresentIn, }; acc[index].semantic_fields.push(semanticField); diff --git a/x-pack/solutions/search/plugins/search_playground/server/utils/get_value_for_selected_field.test.ts b/x-pack/solutions/search/plugins/search_playground/server/utils/get_value_for_selected_field.test.ts index 7eae929cc70c0..11351c56adb97 100644 --- a/x-pack/solutions/search/plugins/search_playground/server/utils/get_value_for_selected_field.test.ts +++ b/x-pack/solutions/search/plugins/search_playground/server/utils/get_value_for_selected_field.test.ts @@ -78,49 +78,30 @@ describe('getValueForSelectedField', () => { expect(getValueForSelectedField(hit, 'bla.sources')).toBe(''); }); - test('should return when its a chunked passage', () => { + test('should return when it has highlighted messages', () => { const hit = { - _index: 'sample-index', + _index: 'books', _id: '8jSNY48B6iHEi98DL1C-', _score: 0.7789394, _source: { - test: 'The Shawshank Redemption', + test: 'The Big Bang and Black Holes', metadata: { source: - 'Over the course of several years, two convicts form a friendship, seeking consolation and, eventually, redemption through basic compassion', + 'This book explores the origins of the universe, beginning with the Big Bang—an immense explosion that created space, time, and matter. It delves into how black holes, regions of space where gravity is so strong that not even light can escape, play a crucial role in the evolution of galaxies and the universe as a whole. Stephen Hawking’s groundbreaking discoveries about black hole radiation, often referred to as Hawking Radiation, are also discussed in detail.', }, }, - inner_hits: { - 'sample-index.test': { - hits: { - hits: [ - { - _source: { - text: 'Over the course of several years', - }, - }, - { - _source: { - text: 'two convicts form a friendship', - }, - }, - { - _source: { - text: 'seeking consolation and, eventually, redemption through basic compassion', - }, - }, - ], - }, - }, + highlight: { + test: [ + 'This book explores the origins of the universe.', + 'The beginning with the Big Bang—an immense explosion that created space, time, and matter. It delves into how black holes, regions of space where gravity is so strong that not even light can escape, play a crucial role in the evolution of galaxies and the universe as a whole. Stephen Hawking’s groundbreaking discoveries about black hole radiation, often referred to as Hawking Radiation, are also discussed in detail.', + ], }, }; expect(getValueForSelectedField(hit as any, 'test')).toMatchInlineSnapshot(` - "Over the course of several years - --- - two convicts form a friendship + "This book explores the origins of the universe. --- - seeking consolation and, eventually, redemption through basic compassion" + The beginning with the Big Bang—an immense explosion that created space, time, and matter. It delves into how black holes, regions of space where gravity is so strong that not even light can escape, play a crucial role in the evolution of galaxies and the universe as a whole. Stephen Hawking’s groundbreaking discoveries about black hole radiation, often referred to as Hawking Radiation, are also discussed in detail." `); }); diff --git a/x-pack/solutions/search/plugins/search_playground/server/utils/get_value_for_selected_field.ts b/x-pack/solutions/search/plugins/search_playground/server/utils/get_value_for_selected_field.ts index 5556e407de979..fe0772a314327 100644 --- a/x-pack/solutions/search/plugins/search_playground/server/utils/get_value_for_selected_field.ts +++ b/x-pack/solutions/search/plugins/search_playground/server/utils/get_value_for_selected_field.ts @@ -14,11 +14,8 @@ export const getValueForSelectedField = (hit: SearchHit, path: string): string = } // for semantic_text matches - const innerHitPath = `${hit._index}.${path}`; - if (!!hit.inner_hits?.[innerHitPath]) { - return hit.inner_hits[innerHitPath].hits.hits - .map((innerHit) => innerHit._source.text) - .join('\n --- \n'); + if (hit.highlight && hit.highlight[path]) { + return hit.highlight[path].flat().join('\n --- \n'); } return has(hit._source, `${path}.text`) diff --git a/x-pack/solutions/search/plugins/search_playground/server/utils/stream_factory.ts b/x-pack/solutions/search/plugins/search_playground/server/utils/stream_factory.ts index 529b913293021..c21d9cc005fa3 100644 --- a/x-pack/solutions/search/plugins/search_playground/server/utils/stream_factory.ts +++ b/x-pack/solutions/search/plugins/search_playground/server/utils/stream_factory.ts @@ -107,7 +107,7 @@ export function streamFactory(logger: Logger, isCloud: boolean = false): StreamF ); if (line === undefined) { - logger.error('Stream chunk must not be undefined.'); + logDebugMessage('Stream chunk must not be undefined.'); return; } diff --git a/x-pack/solutions/search/plugins/search_synonyms/common/api_routes.ts b/x-pack/solutions/search/plugins/search_synonyms/common/api_routes.ts new file mode 100644 index 0000000000000..096aca8cbb2b2 --- /dev/null +++ b/x-pack/solutions/search/plugins/search_synonyms/common/api_routes.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export enum APIRoutes { + SYNONYM_SETS = '/internal/search_synonyms/synonyms', + SYNONYM_SET_ID = '/internal/search_synonyms/synonyms/{synonymsSetId}', +} diff --git a/x-pack/solutions/search/plugins/search_synonyms/common/pagination.ts b/x-pack/solutions/search/plugins/search_synonyms/common/pagination.ts new file mode 100644 index 0000000000000..5acaaf4654b81 --- /dev/null +++ b/x-pack/solutions/search/plugins/search_synonyms/common/pagination.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. + */ + +export const DEFAULT_PAGE_VALUE: Page = { + from: 0, + size: 10, +}; + +export interface Pagination { + pageIndex: number; + pageSize: number; + totalItemCount: number; +} + +export interface Page { + from: number; // current page index, 0-based + size: number; +} + +export interface Paginate { + _meta: Pagination; + data: T[]; +} + +export function paginationToPage(pagination: Pagination): Page { + return { + from: pagination.pageIndex * pagination.pageSize, + size: pagination.pageSize, + }; +} +export function pageToPagination(page: { from: number; size: number; total: number }) { + // Prevent divide-by-zero-error + const pageIndex = page.size ? Math.trunc(page.from / page.size) : 0; + return { + pageIndex, + pageSize: page.size, + totalItemCount: page.total, + }; +} diff --git a/x-pack/solutions/search/plugins/search_synonyms/public/application.tsx b/x-pack/solutions/search/plugins/search_synonyms/public/application.tsx index fb724a91a22ab..55bc184b647ff 100644 --- a/x-pack/solutions/search/plugins/search_synonyms/public/application.tsx +++ b/x-pack/solutions/search/plugins/search_synonyms/public/application.tsx @@ -12,9 +12,11 @@ import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { I18nProvider } from '@kbn/i18n-react'; import { Route, Router, Routes } from '@kbn/shared-ux-router'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { AppPluginStartDependencies } from './types'; import { SearchSynonymsOverview } from './components/overview/overview'; +const queryClient = new QueryClient({}); export const renderApp = async ( core: CoreStart, services: AppPluginStartDependencies, @@ -24,13 +26,15 @@ export const renderApp = async ( - - - - - - - + + + + + + + + + , diff --git a/x-pack/solutions/search/plugins/search_synonyms/public/components/overview/overview.tsx b/x-pack/solutions/search/plugins/search_synonyms/public/components/overview/overview.tsx index 54d20246e7f92..e36ae0314a189 100644 --- a/x-pack/solutions/search/plugins/search_synonyms/public/components/overview/overview.tsx +++ b/x-pack/solutions/search/plugins/search_synonyms/public/components/overview/overview.tsx @@ -8,13 +8,17 @@ import React, { useMemo } from 'react'; import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; +import { EuiLoadingSpinner } from '@elastic/eui'; import { useKibana } from '../../hooks/use_kibana'; +import { SynonymSets } from '../synonym_sets/synonym_sets'; +import { useFetchSynonymsSets } from '../../hooks/use_fetch_synonyms_sets'; import { EmptyPrompt } from '../empty_prompt/empty_prompt'; export const SearchSynonymsOverview = () => { const { services: { console: consolePlugin, history, searchNavigation }, } = useKibana(); + const { data: synonymsData, isInitialLoading } = useFetchSynonymsSets(); const embeddableConsole = useMemo( () => (consolePlugin?.EmbeddableConsole ? : null), @@ -28,7 +32,16 @@ export const SearchSynonymsOverview = () => { data-test-subj="searchSynonymsOverviewPage" solutionNav={searchNavigation?.useClassicNavigation(history)} > - + + {isInitialLoading && } + + {!isInitialLoading && synonymsData && synonymsData._meta.totalItemCount > 0 && ( + + )} + {!isInitialLoading && synonymsData && synonymsData._meta.totalItemCount === 0 && ( + + )} + {embeddableConsole} ); diff --git a/x-pack/solutions/search/plugins/search_synonyms/public/components/synonym_sets/delete_synonyms_set_modal.test.tsx b/x-pack/solutions/search/plugins/search_synonyms/public/components/synonym_sets/delete_synonyms_set_modal.test.tsx new file mode 100644 index 0000000000000..a36b0d2d2f1ab --- /dev/null +++ b/x-pack/solutions/search/plugins/search_synonyms/public/components/synonym_sets/delete_synonyms_set_modal.test.tsx @@ -0,0 +1,105 @@ +/* + * 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 { DeleteSynonymsSetModal } from './delete_synonyms_set_modal'; +import { act, fireEvent, render, screen } from '@testing-library/react'; +import { useDeleteSynonymsSet } from '../../hooks/use_delete_synonyms_set'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; + +jest.mock('../../hooks/use_delete_synonyms_set', () => ({ + useDeleteSynonymsSet: jest.fn(() => ({ + mutate: jest.fn(), + })), +})); + +describe('DeleteSynonymsSetModal', () => { + const queryClient = new QueryClient(); + const Wrapper = ({ children }: { children?: React.ReactNode }) => ( + {children} + ); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should not use mutation when cancel is pressed', () => { + const onClose = jest.fn(); + const mutate = jest.fn(); + (useDeleteSynonymsSet as unknown as jest.Mock).mockReturnValue({ + mutate, + }); + render( + + + + ); + + act(() => { + fireEvent.click(screen.getByText('Cancel')); + }); + + expect(onClose).toHaveBeenCalled(); + expect(useDeleteSynonymsSet).toHaveBeenCalled(); + expect(mutate).not.toHaveBeenCalled(); + }); + + it('should delete the synonyms set when delete is pressed', () => { + const onClose = jest.fn(); + const mutate = jest.fn(); + + (useDeleteSynonymsSet as unknown as jest.Mock).mockReturnValue({ + mutate, + }); + + render( + + + + ); + + act(() => { + fireEvent.click(screen.getByText('Delete')); + }); + + expect(useDeleteSynonymsSet).toHaveBeenCalled(); + expect(onClose).not.toHaveBeenCalled(); + expect(mutate).toHaveBeenCalledWith({ synonymsSetId: '123' }); + }); + + it('should show error message if synonyms set is attached to an index', () => { + const onClose = jest.fn(); + const mutate = jest.fn(); + + (useDeleteSynonymsSet as unknown as jest.Mock).mockReturnValue({ + mutate, + }); + + render( + + + + ); + + act(() => { + fireEvent.click(screen.getByText('Delete')); + }); + + expect(useDeleteSynonymsSet).toHaveBeenCalled(); + expect(onClose).not.toHaveBeenCalled(); + expect(mutate).toHaveBeenCalledWith({ synonymsSetId: '123' }); + + act(() => { + (useDeleteSynonymsSet as unknown as jest.Mock).mock.calls[0][1]( + 'Synonyms set is attached to an index' + ); + }); + + expect(screen.getByText('Synonyms set is attached to an index')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/solutions/search/plugins/search_synonyms/public/components/synonym_sets/delete_synonyms_set_modal.tsx b/x-pack/solutions/search/plugins/search_synonyms/public/components/synonym_sets/delete_synonyms_set_modal.tsx new file mode 100644 index 0000000000000..c1c776f1d513d --- /dev/null +++ b/x-pack/solutions/search/plugins/search_synonyms/public/components/synonym_sets/delete_synonyms_set_modal.tsx @@ -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 React, { useState } from 'react'; + +import { EuiCodeBlock, EuiConfirmModal } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { useDeleteSynonymsSet } from '../../hooks/use_delete_synonyms_set'; + +export interface DeleteSynonymsSetModalProps { + synonymsSetId: string; + closeDeleteModal: () => void; +} + +export const DeleteSynonymsSetModal = ({ + closeDeleteModal, + synonymsSetId, +}: DeleteSynonymsSetModalProps) => { + const [error, setError] = useState(null); + const [isLoading, setIsLoading] = useState(false); + const onSuccess = () => { + setIsLoading(false); + closeDeleteModal(); + }; + + const onError = (errorMessage: string) => { + setIsLoading(false); + setError(errorMessage); + }; + const { mutate: deleteEndpoint } = useDeleteSynonymsSet(onSuccess, onError); + const deleteOperation = () => { + setIsLoading(true); + deleteEndpoint({ synonymsSetId }); + }; + return ( + + {i18n.translate('xpack.searchSynonyms.deleteSynonymsSetModal.body', { + defaultMessage: + 'Deleting a synonym set currently in use will cause failures in the ingest and query attempts targeting the related semantic text fields.', + })} + {error && ( + + {error} + + )} + + ); +}; diff --git a/x-pack/solutions/search/plugins/search_synonyms/public/components/synonym_sets/synonym_sets.test.tsx b/x-pack/solutions/search/plugins/search_synonyms/public/components/synonym_sets/synonym_sets.test.tsx new file mode 100644 index 0000000000000..a06d4bad66edc --- /dev/null +++ b/x-pack/solutions/search/plugins/search_synonyms/public/components/synonym_sets/synonym_sets.test.tsx @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { render, screen } from '@testing-library/react'; +import { SynonymSets } from './synonym_sets'; + +jest.mock('../../hooks/use_fetch_synonyms_sets', () => ({ + useFetchSynonymsSets: () => ({ + data: { + data: [ + { + synonyms_set: 'Synonyms Set 1', + count: 2, + }, + { + synonyms_set: 'Synonyms Set 2', + count: 3, + }, + ], + _meta: { pageIndex: 0, pageSize: 10, totalItemCount: 2 }, + }, + isLoading: false, + isError: false, + }), +})); + +describe('Search Synonym Sets list', () => { + it('should render the list with synonym sets', () => { + render(); + const synonymSetTable = screen.getByTestId('synonyms-set-table'); + expect(synonymSetTable).toBeInTheDocument(); + + const synonymSetItemNames = screen.getAllByTestId('synonyms-set-item-name'); + expect(synonymSetItemNames).toHaveLength(2); + expect(synonymSetItemNames[0].textContent).toBe('Synonyms Set 1'); + expect(synonymSetItemNames[1].textContent).toBe('Synonyms Set 2'); + + const synonymSetItemRuleCounts = screen.getAllByTestId('synonyms-set-item-rule-count'); + expect(synonymSetItemRuleCounts).toHaveLength(2); + expect(synonymSetItemRuleCounts[0].textContent).toBe('2'); + expect(synonymSetItemRuleCounts[1].textContent).toBe('3'); + + const synonymSetItemPageSize = screen.getByTestId('tablePaginationPopoverButton'); + const synonymSetPageButton = screen.getByTestId('pagination-button-0'); + expect(synonymSetItemPageSize).toBeInTheDocument(); + expect(synonymSetPageButton).toBeInTheDocument(); + }); +}); diff --git a/x-pack/solutions/search/plugins/search_synonyms/public/components/synonym_sets/synonym_sets.tsx b/x-pack/solutions/search/plugins/search_synonyms/public/components/synonym_sets/synonym_sets.tsx new file mode 100644 index 0000000000000..acce732d9f763 --- /dev/null +++ b/x-pack/solutions/search/plugins/search_synonyms/public/components/synonym_sets/synonym_sets.tsx @@ -0,0 +1,106 @@ +/* + * 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 { SynonymsGetSynonymsSetsSynonymsSetItem } from '@elastic/elasticsearch/lib/api/types'; +import { EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React, { useState } from 'react'; +import { DEFAULT_PAGE_VALUE, paginationToPage } from '../../../common/pagination'; +import { useFetchSynonymsSets } from '../../hooks/use_fetch_synonyms_sets'; +import { DeleteSynonymsSetModal } from './delete_synonyms_set_modal'; + +export const SynonymSets = () => { + const [pageIndex, setPageIndex] = useState(0); + const [pageSize, setPageSize] = useState(DEFAULT_PAGE_VALUE.size); + const { from } = paginationToPage({ pageIndex, pageSize, totalItemCount: 0 }); + const { data: synonyms } = useFetchSynonymsSets({ from, size: pageSize }); + const [synonymsSetToDelete, setSynonymsSetToDelete] = React.useState(null); + + if (!synonyms) { + return null; + } + + const pagination = { + initialPageSize: 10, + pageSizeOptions: [10, 25, 50], + ...synonyms._meta, + pageSize, + pageIndex, + }; + const columns: Array> = [ + { + field: 'synonyms_set', + name: i18n.translate('xpack.searchSynonyms.synonymsSetTable.nameColumn', { + defaultMessage: 'Synonyms Set', + }), + render: (name: string) =>
{name}
, + }, + { + field: 'count', + name: i18n.translate('xpack.searchSynonyms.synonymsSetTable.ruleCount', { + defaultMessage: 'Rule Count', + }), + render: (ruleCount: number) => ( +
{ruleCount}
+ ), + }, + { + actions: [ + { + name: i18n.translate('xpack.searchSynonyms.synonymsSetTable.actions.delete', { + defaultMessage: 'Delete', + }), + description: (synonymsSet: SynonymsGetSynonymsSetsSynonymsSetItem) => + i18n.translate('xpack.searchSynonyms.synonymsSetTable.actions.deleteDescription', { + defaultMessage: 'Delete synonyms set with {name}', + values: { name: synonymsSet.synonyms_set }, + }), + icon: 'trash', + color: 'danger', + type: 'icon', + onClick: (synonymsSet: SynonymsGetSynonymsSetsSynonymsSetItem) => { + setSynonymsSetToDelete(synonymsSet.synonyms_set); + }, + }, + { + name: i18n.translate('xpack.searchSynonyms.synonymsSetTable.actions.edit', { + defaultMessage: 'Edit', + }), + description: (synonymsSet: SynonymsGetSynonymsSetsSynonymsSetItem) => + i18n.translate('xpack.searchSynonyms.synonymsSetTable.actions.editDescription', { + defaultMessage: 'Edit synonyms set {name}', + values: { name: synonymsSet.synonyms_set }, + }), + icon: 'pencil', + color: 'text', + type: 'icon', + onClick: () => {}, + }, + ], + }, + ]; + return ( +
+ {synonymsSetToDelete && ( + setSynonymsSetToDelete(null)} + /> + )} + { + setPageIndex(changedPage.index); + setPageSize(changedPage.size); + }} + /> +
+ ); +}; diff --git a/x-pack/solutions/search/plugins/search_synonyms/public/hooks/use_delete_synonyms_set.test.tsx b/x-pack/solutions/search/plugins/search_synonyms/public/hooks/use_delete_synonyms_set.test.tsx new file mode 100644 index 0000000000000..a5d09079dea1d --- /dev/null +++ b/x-pack/solutions/search/plugins/search_synonyms/public/hooks/use_delete_synonyms_set.test.tsx @@ -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 React from 'react'; + +import { renderHook, waitFor } from '@testing-library/react'; +import { useKibana } from './use_kibana'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { useDeleteSynonymsSet } from './use_delete_synonyms_set'; + +jest.mock('./use_kibana'); + +const mockUseKibana = useKibana as jest.Mock; +const mockDelete = jest.fn(); +const mockAddSuccess = jest.fn(); +const mockAddError = jest.fn(); + +describe('useDeleteSynonymsSet hook', () => { + beforeEach(() => { + mockUseKibana.mockReturnValue({ + services: { + http: { + delete: mockDelete, + }, + notifications: { + toasts: { + addSuccess: mockAddSuccess, + addError: mockAddError, + }, + }, + }, + }); + mockDelete.mockResolvedValue({}); + }); + + const wrapper = ({ children }: { children: React.ReactNode }) => { + const queryClient = new QueryClient(); + return {children}; + }; + + it('should delete the synonyms set if no index is attached', async () => { + const { result } = renderHook(() => useDeleteSynonymsSet(), { wrapper }); + + result.current.mutate({ synonymsSetId: '123' }); + await waitFor(() => + expect(mockDelete).toHaveBeenCalledWith('/internal/search_synonyms/synonyms/123') + ); + }); + + it('should show an error message if synonyms set is attached to an index', async () => { + const error = { + body: { message: 'Synonyms set is attached to an index and cannot be deleted' }, + }; + mockDelete.mockRejectedValue(error); + const { result } = renderHook(() => useDeleteSynonymsSet(), { wrapper }); + + result.current.mutate({ synonymsSetId: '123' }); + await waitFor(() => + expect(mockAddError).toHaveBeenCalledWith(new Error(error.body.message), { + title: 'Error deleting synonyms set', + toastMessage: error.body.message, + }) + ); + }); +}); diff --git a/x-pack/solutions/search/plugins/search_synonyms/public/hooks/use_delete_synonyms_set.ts b/x-pack/solutions/search/plugins/search_synonyms/public/hooks/use_delete_synonyms_set.ts new file mode 100644 index 0000000000000..f29da4ea5fb82 --- /dev/null +++ b/x-pack/solutions/search/plugins/search_synonyms/public/hooks/use_delete_synonyms_set.ts @@ -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 { useMutation, useQueryClient } from '@tanstack/react-query'; +import { i18n } from '@kbn/i18n'; +import { KibanaServerError } from '@kbn/kibana-utils-plugin/common'; +import { useKibana } from './use_kibana'; + +interface MutationArgs { + synonymsSetId: string; +} + +export const useDeleteSynonymsSet = (onSuccess?: () => void, onError?: (error: string) => void) => { + const queryClient = useQueryClient(); + const { + services: { http, notifications }, + } = useKibana(); + + return useMutation( + async ({ synonymsSetId }: MutationArgs) => { + return await http.delete<{ acknowledged: boolean }>( + `/internal/search_synonyms/synonyms/${synonymsSetId}` + ); + }, + { + onSuccess: (_, { synonymsSetId }) => { + queryClient.invalidateQueries(['synonyms-sets-fetch']); + notifications?.toasts?.addSuccess({ + title: i18n.translate('xpack.searchSynonyms.deleteSynonymsSetSuccess', { + defaultMessage: 'Synonyms set {synonymsSetId} deleted', + values: { synonymsSetId }, + }), + }); + if (onSuccess) { + onSuccess(); + } + }, + onError: (error: { body: KibanaServerError }) => { + if (onError) { + onError(error.body.message); + } else { + notifications?.toasts?.addError(new Error(error.body.message), { + title: i18n.translate('xpack.searchSynonyms.deleteSynonymsSetError', { + defaultMessage: 'Error deleting synonyms set', + }), + toastMessage: error.body.message, + }); + } + }, + } + ); +}; diff --git a/x-pack/solutions/search/plugins/search_synonyms/public/hooks/use_fetch_synonyms_sets.test.ts b/x-pack/solutions/search/plugins/search_synonyms/public/hooks/use_fetch_synonyms_sets.test.ts new file mode 100644 index 0000000000000..61b24ac3f69cd --- /dev/null +++ b/x-pack/solutions/search/plugins/search_synonyms/public/hooks/use_fetch_synonyms_sets.test.ts @@ -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 { renderHook, waitFor } from '@testing-library/react'; + +const mockHttpGet = jest.fn(); + +jest.mock('@tanstack/react-query', () => ({ + useQuery: jest.fn().mockImplementation(async ({ queryKey, queryFn, opts }) => { + try { + const res = await queryFn(); + return Promise.resolve(res); + } catch (e) { + // opts.onError(e); + } + }), +})); + +jest.mock('./use_kibana', () => ({ + useKibana: jest.fn().mockReturnValue({ + services: { + http: { + get: mockHttpGet, + }, + notifications: { + toasts: { + addError: jest.fn(), + }, + }, + }, + }), +})); + +describe('useFetchSynonymsSet Hook', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should return synonyms set', async () => { + const synonyms = [ + { + id: '1', + synonyms: ['foo', 'bar'], + }, + ]; + mockHttpGet.mockReturnValue(synonyms); + const { useFetchSynonymsSets } = jest.requireActual('./use_fetch_synonyms_sets'); + + const { result } = renderHook(() => useFetchSynonymsSets()); + await waitFor(() => expect(result.current).resolves.toStrictEqual(synonyms)); + }); +}); diff --git a/x-pack/solutions/search/plugins/search_synonyms/public/hooks/use_fetch_synonyms_sets.ts b/x-pack/solutions/search/plugins/search_synonyms/public/hooks/use_fetch_synonyms_sets.ts new file mode 100644 index 0000000000000..b2bd6dbd71788 --- /dev/null +++ b/x-pack/solutions/search/plugins/search_synonyms/public/hooks/use_fetch_synonyms_sets.ts @@ -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 { useQuery } from '@tanstack/react-query'; +import type { SynonymsGetSynonymsSetsSynonymsSetItem } from '@elastic/elasticsearch/lib/api/types'; +import { DEFAULT_PAGE_VALUE, Page, Paginate } from '../../common/pagination'; +import { APIRoutes } from '../../common/api_routes'; +import { useKibana } from './use_kibana'; + +export const useFetchSynonymsSets = (page: Page = DEFAULT_PAGE_VALUE) => { + const { + services: { http }, + } = useKibana(); + return useQuery({ + queryKey: ['synonyms-sets-fetch', page.from, page.size], + queryFn: async () => { + return await http.get>( + APIRoutes.SYNONYM_SETS, + { + query: { from: page.from, size: page.size }, + } + ); + }, + }); +}; diff --git a/x-pack/solutions/search/plugins/search_synonyms/server/lib/delete_synonyms_set.test.ts b/x-pack/solutions/search/plugins/search_synonyms/server/lib/delete_synonyms_set.test.ts new file mode 100644 index 0000000000000..80883c8082f9d --- /dev/null +++ b/x-pack/solutions/search/plugins/search_synonyms/server/lib/delete_synonyms_set.test.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 { ElasticsearchClient } from '@kbn/core/server'; +import { deleteSynonymsSet } from './delete_synonyms_set'; + +describe('delete synonyms sets lib function', () => { + const mockClient = { + synonyms: { + deleteSynonym: jest.fn(), + }, + }; + + const client = () => mockClient as unknown as ElasticsearchClient; + it('should delete synonym set when it is not attached to anything', async () => { + mockClient.synonyms.deleteSynonym.mockResolvedValue({ acknowledged: true }); + const response = await deleteSynonymsSet(client(), 'my-synonyms-set'); + expect(mockClient.synonyms.deleteSynonym).toHaveBeenCalledWith({ id: 'my-synonyms-set' }); + expect(response).toEqual({ acknowledged: true }); + }); + + it('should throw if synonym set is attached to an index', async () => { + mockClient.synonyms.deleteSynonym.mockRejectedValue( + new Error( + 'synonyms set [my-synonyms-set] cannot be deleted as it is used in the following indices: index-1, index-2' + ) + ); + expect(mockClient.synonyms.deleteSynonym).toHaveBeenCalledWith({ id: 'my-synonyms-set' }); + await expect(deleteSynonymsSet(client(), 'my-synonyms-set')).rejects.toThrowError( + 'synonyms set [my-synonyms-set] cannot be deleted as it is used in the following indices: index-1, index-2' + ); + }); +}); diff --git a/x-pack/solutions/search/plugins/search_synonyms/server/lib/delete_synonyms_set.ts b/x-pack/solutions/search/plugins/search_synonyms/server/lib/delete_synonyms_set.ts new file mode 100644 index 0000000000000..b79a4360caf20 --- /dev/null +++ b/x-pack/solutions/search/plugins/search_synonyms/server/lib/delete_synonyms_set.ts @@ -0,0 +1,12 @@ +/* + * 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 } from '@kbn/core/server'; + +export const deleteSynonymsSet = async (client: ElasticsearchClient, synonymsSetId: string) => { + return await client.synonyms.deleteSynonym({ id: synonymsSetId }); +}; diff --git a/x-pack/solutions/search/plugins/search_synonyms/server/lib/fetch_synonym_sets.test.ts b/x-pack/solutions/search/plugins/search_synonyms/server/lib/fetch_synonym_sets.test.ts new file mode 100644 index 0000000000000..e96c2bc5489ae --- /dev/null +++ b/x-pack/solutions/search/plugins/search_synonyms/server/lib/fetch_synonym_sets.test.ts @@ -0,0 +1,60 @@ +/* + * 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 } from '@kbn/core/server'; +import { fetchSynonymSets } from './fetch_synonym_sets'; + +describe('fetch synonym sets lib function', () => { + const mockClient = { + security: { + hasPrivileges: jest.fn(), + }, + synonyms: { + getSynonymsSets: jest.fn(), + }, + }; + + const client = () => mockClient as unknown as ElasticsearchClient; + + beforeEach(() => { + jest.clearAllMocks(); + }); + it('should return synonym sets', async () => { + mockClient.synonyms.getSynonymsSets.mockResolvedValue({ + count: 2, + results: [ + { + synonyms_set: 'my_synonyms_set', + count: 2, + }, + { + synonyms_set: 'my_synonyms_set_2', + count: 3, + }, + ], + }); + + const result = await fetchSynonymSets(client(), { from: 0, size: 10 }); + expect(result).toEqual({ + _meta: { + pageIndex: 0, + pageSize: 10, + totalItemCount: 2, + }, + data: [ + { + synonyms_set: 'my_synonyms_set', + count: 2, + }, + { + synonyms_set: 'my_synonyms_set_2', + count: 3, + }, + ], + }); + }); +}); diff --git a/x-pack/solutions/search/plugins/search_synonyms/server/lib/fetch_synonym_sets.ts b/x-pack/solutions/search/plugins/search_synonyms/server/lib/fetch_synonym_sets.ts new file mode 100644 index 0000000000000..82e25fdb80170 --- /dev/null +++ b/x-pack/solutions/search/plugins/search_synonyms/server/lib/fetch_synonym_sets.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 { SynonymsGetSynonymsSetsSynonymsSetItem } from '@elastic/elasticsearch/lib/api/types'; +import { ElasticsearchClient } from '@kbn/core/server'; +import { Page, Paginate, pageToPagination } from '../../common/pagination'; + +export const fetchSynonymSets = async ( + client: ElasticsearchClient, + { from, size }: Page +): Promise> => { + const result = await client.synonyms.getSynonymsSets({ + from, + size, + }); + const _meta = pageToPagination({ from, size, total: result.count }); + return { _meta, data: result.results }; +}; diff --git a/x-pack/solutions/search/plugins/search_synonyms/server/routes.ts b/x-pack/solutions/search/plugins/search_synonyms/server/routes.ts index 9411887ffb311..a175f05cc874a 100644 --- a/x-pack/solutions/search/plugins/search_synonyms/server/routes.ts +++ b/x-pack/solutions/search/plugins/search_synonyms/server/routes.ts @@ -6,5 +6,99 @@ */ import { IRouter, Logger } from '@kbn/core/server'; +import { schema } from '@kbn/config-schema'; +import { APIRoutes } from '../common/api_routes'; -export function defineRoutes({ logger, router }: { logger: Logger; router: IRouter }) {} +import { errorHandler } from './utils/error_handler'; +import { fetchSynonymSets } from './lib/fetch_synonym_sets'; +import { DEFAULT_PAGE_VALUE } from '../common/pagination'; +import { deleteSynonymsSet } from './lib/delete_synonyms_set'; + +export function defineRoutes({ logger, router }: { logger: Logger; router: IRouter }) { + router.get( + { + path: APIRoutes.SYNONYM_SETS, + options: { + access: 'internal', + tags: ['synonyms:read'], + }, + security: { + authz: { + requiredPrivileges: ['synonyms:read'], + }, + }, + validate: { + query: schema.object({ + from: schema.number({ defaultValue: DEFAULT_PAGE_VALUE.from }), + size: schema.number({ defaultValue: DEFAULT_PAGE_VALUE.size }), + }), + }, + }, + errorHandler(logger)(async (context, request, response) => { + const core = await context.core; + const { + client: { asCurrentUser }, + } = core.elasticsearch; + const user = core.security.authc.getCurrentUser(); + if (!user) { + return response.customError({ + statusCode: 502, + body: 'Could not retrieve current user, security plugin is not ready', + }); + } + const hasSearchSynonymsPrivilege = await asCurrentUser.security.hasPrivileges({ + cluster: ['manage_search_synonyms'], + }); + if (!hasSearchSynonymsPrivilege.has_all_requested) { + return response.forbidden({ + body: "Your user doesn't have manage_search_synonyms privileges", + }); + } + const result = await fetchSynonymSets(asCurrentUser, { + from: request.query.from, + size: request.query.size, + }); + return response.ok({ + body: result, + }); + }) + ); + + router.delete( + { + path: APIRoutes.SYNONYM_SET_ID, + options: { + access: 'internal', + tags: ['synonyms:write', 'synonyms:read'], + }, + security: { + authz: { + requiredPrivileges: ['synonyms:write', 'synonyms:read'], + }, + }, + validate: { + params: schema.object({ + synonymsSetId: schema.string(), + }), + }, + }, + errorHandler(logger)(async (context, request, response) => { + const core = await context.core; + const { + client: { asCurrentUser }, + } = core.elasticsearch; + const user = core.security.authc.getCurrentUser(); + if (!user) { + return response.customError({ + statusCode: 502, + body: 'Could not retrieve current user, security plugin is not ready', + }); + } + const synonymsSetId = request.params.synonymsSetId; + const result = await deleteSynonymsSet(asCurrentUser, synonymsSetId); + return response.ok({ + body: result, + }); + }) + ); +} diff --git a/x-pack/solutions/search/plugins/search_synonyms/server/utils/error_handler.ts b/x-pack/solutions/search/plugins/search_synonyms/server/utils/error_handler.ts new file mode 100644 index 0000000000000..b4b3894125bdb --- /dev/null +++ b/x-pack/solutions/search/plugins/search_synonyms/server/utils/error_handler.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 { RequestHandlerWrapper } from '@kbn/core-http-server'; +import { KibanaServerError } from '@kbn/kibana-utils-plugin/common'; +import type { Logger } from '@kbn/logging'; + +function isKibanaServerError(error: any): error is KibanaServerError { + return error.statusCode && error.message; +} + +export const errorHandler: (logger: Logger) => RequestHandlerWrapper = (logger) => (handler) => { + return async (context, request, response) => { + try { + return await handler(context, request, response); + } catch (e) { + logger.error(e); + if (isKibanaServerError(e)) { + return response.customError({ statusCode: e.statusCode, body: e.message }); + } + throw e; + } + }; +}; diff --git a/x-pack/solutions/search/plugins/search_synonyms/tsconfig.json b/x-pack/solutions/search/plugins/search_synonyms/tsconfig.json index 027f552896e68..d1f54f9f43f0c 100644 --- a/x-pack/solutions/search/plugins/search_synonyms/tsconfig.json +++ b/x-pack/solutions/search/plugins/search_synonyms/tsconfig.json @@ -22,6 +22,9 @@ "@kbn/search-navigation", "@kbn/doc-links", "@kbn/shared-ux-page-kibana-template", + "@kbn/core-http-server", + "@kbn/kibana-utils-plugin", + "@kbn/logging", ], "exclude": [ "target/**/*", diff --git a/x-pack/solutions/security/packages/distribution_bar/src/distribution_bar.stories.tsx b/x-pack/solutions/security/packages/distribution_bar/src/distribution_bar.stories.tsx index c1b292c3f08cc..e3115f3e8758f 100644 --- a/x-pack/solutions/security/packages/distribution_bar/src/distribution_bar.stories.tsx +++ b/x-pack/solutions/security/packages/distribution_bar/src/distribution_bar.stories.tsx @@ -5,7 +5,6 @@ * 2.0. */ import React from 'react'; -import { euiThemeVars } from '@kbn/ui-theme'; import { EuiTitle, EuiSpacer } from '@elastic/eui'; import { DistributionBar as DistributionBarComponent } from '..'; @@ -13,13 +12,13 @@ const mockStatsFindings = [ { key: 'passed', count: 90, - color: euiThemeVars.euiColorVis0, + color: 'green', label: 'Passed', }, { key: 'failed', count: 10, - color: euiThemeVars.euiColorVis9, + color: 'red', label: <>{'Failed'}, }, ]; @@ -28,22 +27,22 @@ const mockStatsAlerts = [ { key: 'low', count: 1000, - color: euiThemeVars.euiColorVis0, + color: 'green', }, { key: 'medium', count: 800, - color: euiThemeVars.euiColorVis5, + color: 'gold', }, { key: 'high', count: 300, - color: euiThemeVars.euiColorVis7, + color: 'orange', }, { key: 'critical', count: 50, - color: euiThemeVars.euiColorVis9, + color: 'red', }, ]; diff --git a/x-pack/solutions/security/packages/distribution_bar/tsconfig.json b/x-pack/solutions/security/packages/distribution_bar/tsconfig.json index 277fe500caa48..c52c97337264f 100644 --- a/x-pack/solutions/security/packages/distribution_bar/tsconfig.json +++ b/x-pack/solutions/security/packages/distribution_bar/tsconfig.json @@ -13,7 +13,6 @@ }, "include": ["**/*.ts", "**/*.tsx"], "kbn_references": [ - "@kbn/ui-theme", ], "exclude": ["target/**/*"] } diff --git a/x-pack/solutions/security/packages/features/config.ts b/x-pack/solutions/security/packages/features/config.ts index 9fa14ab0ba7c2..945623502029e 100644 --- a/x-pack/solutions/security/packages/features/config.ts +++ b/x-pack/solutions/security/packages/features/config.ts @@ -9,5 +9,7 @@ export { securityDefaultProductFeaturesConfig } from './src/security/product_fea export { getCasesDefaultProductFeaturesConfig } from './src/cases/product_feature_config'; export { assistantDefaultProductFeaturesConfig } from './src/assistant/product_feature_config'; export { attackDiscoveryDefaultProductFeaturesConfig } from './src/attack_discovery/product_feature_config'; +export { timelineDefaultProductFeaturesConfig } from './src/timeline/product_feature_config'; +export { notesDefaultProductFeaturesConfig } from './src/notes/product_feature_config'; export { createEnabledProductFeaturesConfigMap } from './src/helpers'; diff --git a/x-pack/solutions/security/packages/features/product_features.ts b/x-pack/solutions/security/packages/features/product_features.ts index 67d61f21fae5e..1f55fd51bae1d 100644 --- a/x-pack/solutions/security/packages/features/product_features.ts +++ b/x-pack/solutions/security/packages/features/product_features.ts @@ -5,7 +5,9 @@ * 2.0. */ -export { getSecurityFeature } from './src/security'; +export { getSecurityFeature, getSecurityV2Feature } from './src/security'; export { getCasesFeature, getCasesV2Feature } from './src/cases'; export { getAssistantFeature } from './src/assistant'; export { getAttackDiscoveryFeature } from './src/attack_discovery'; +export { getTimelineFeature } from './src/timeline'; +export { getNotesFeature } from './src/notes'; diff --git a/x-pack/solutions/security/packages/features/src/constants.ts b/x-pack/solutions/security/packages/features/src/constants.ts index c6acab28c4860..9615dc0d278b1 100644 --- a/x-pack/solutions/security/packages/features/src/constants.ts +++ b/x-pack/solutions/security/packages/features/src/constants.ts @@ -9,6 +9,9 @@ export const APP_ID = 'securitySolution' as const; export const SERVER_APP_ID = 'siem' as const; +// New version created in 8.18. It was previously `SERVER_APP_ID`. +export const SECURITY_FEATURE_ID_V2 = 'siemV2' as const; + /** * @deprecated deprecated in 8.17. Use CASE_FEATURE_ID_V2 instead */ @@ -21,6 +24,8 @@ export const SECURITY_SOLUTION_CASES_APP_ID = 'securitySolutionCases' as const; export const ASSISTANT_FEATURE_ID = 'securitySolutionAssistant' as const; export const ATTACK_DISCOVERY_FEATURE_ID = 'securitySolutionAttackDiscovery' as const; +export const TIMELINE_FEATURE_ID = 'securitySolutionTimeline' as const; +export const NOTES_FEATURE_ID = 'securitySolutionNotes' as const; // Same as the plugin id defined by Cloud Security Posture export const CLOUD_POSTURE_APP_ID = 'csp' as const; diff --git a/x-pack/solutions/security/packages/features/src/notes/index.ts b/x-pack/solutions/security/packages/features/src/notes/index.ts new file mode 100644 index 0000000000000..c6ec57b39bb8c --- /dev/null +++ b/x-pack/solutions/security/packages/features/src/notes/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getNotesBaseKibanaFeature } from './kibana_features'; +import type { ProductFeatureParams } from '../types'; +import type { SecurityFeatureParams } from '../security/types'; + +export const getNotesFeature = (params: SecurityFeatureParams): ProductFeatureParams => ({ + baseKibanaFeature: getNotesBaseKibanaFeature(params), + baseKibanaSubFeatureIds: [], + subFeaturesMap: new Map(), +}); diff --git a/x-pack/solutions/security/packages/features/src/notes/kibana_features.ts b/x-pack/solutions/security/packages/features/src/notes/kibana_features.ts new file mode 100644 index 0000000000000..b418a13183ea7 --- /dev/null +++ b/x-pack/solutions/security/packages/features/src/notes/kibana_features.ts @@ -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 { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; +import { i18n } from '@kbn/i18n'; +import { KibanaFeatureScope } from '@kbn/features-plugin/common'; + +import { APP_ID, NOTES_FEATURE_ID } from '../constants'; +import { type BaseKibanaFeatureConfig } from '../types'; +import type { SecurityFeatureParams } from '../security/types'; + +export const getNotesBaseKibanaFeature = ( + params: SecurityFeatureParams +): BaseKibanaFeatureConfig => ({ + id: NOTES_FEATURE_ID, + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.linkSecuritySolutionNotesTitle', + { + defaultMessage: 'Notes', + } + ), + order: 1100, + category: DEFAULT_APP_CATEGORIES.security, + scope: [KibanaFeatureScope.Spaces, KibanaFeatureScope.Security], + app: [NOTES_FEATURE_ID, 'kibana'], + catalogue: [APP_ID], + privileges: { + all: { + app: [NOTES_FEATURE_ID, 'kibana'], + catalogue: [APP_ID], + savedObject: { + all: params.savedObjects, + read: params.savedObjects, + }, + ui: ['read', 'crud'], + api: ['notes_read', 'notes_write'], + }, + read: { + app: [NOTES_FEATURE_ID, 'kibana'], + catalogue: [APP_ID], + savedObject: { + all: [], + read: params.savedObjects, + }, + ui: ['read'], + api: ['notes_read'], + }, + }, +}); diff --git a/x-pack/solutions/security/packages/features/src/notes/product_feature_config.ts b/x-pack/solutions/security/packages/features/src/notes/product_feature_config.ts new file mode 100644 index 0000000000000..596b0af69b62e --- /dev/null +++ b/x-pack/solutions/security/packages/features/src/notes/product_feature_config.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 { ProductFeatureNotesFeatureKey } from '../product_features_keys'; +import type { ProductFeatureKibanaConfig } from '../types'; + +/** + * App features privileges configuration for the notes feature. + * These are the configs that are shared between both offering types (ess and serverless). + * They can be extended on each offering plugin to register privileges using different way on each offering type. + * + * Privileges can be added in different ways: + * - `privileges`: the privileges that will be added directly into the main Security feature. + * - `subFeatureIds`: the ids of the sub-features that will be added into the Security subFeatures entry. + * - `subFeaturesPrivileges`: the privileges that will be added into the existing Security subFeature with the privilege `id` specified. + */ +export const notesDefaultProductFeaturesConfig: Record< + ProductFeatureNotesFeatureKey, + ProductFeatureKibanaConfig +> = { + [ProductFeatureNotesFeatureKey.notes]: { + privileges: { + all: { + api: ['notes_read', 'notes_write'], + ui: ['read', 'crud'], + }, + read: { + api: ['notes_read'], + ui: ['read'], + }, + }, + }, +}; diff --git a/x-pack/solutions/security/packages/features/src/product_features_keys.ts b/x-pack/solutions/security/packages/features/src/product_features_keys.ts index bbc92ae0d978e..b8260762773a8 100644 --- a/x-pack/solutions/security/packages/features/src/product_features_keys.ts +++ b/x-pack/solutions/security/packages/features/src/product_features_keys.ts @@ -114,19 +114,37 @@ export enum ProductFeatureAttackDiscoveryKey { attackDiscovery = 'attack_discovery', } +export enum ProductFeatureTimelineFeatureKey { + /** + * Enables Timeline + */ + timeline = 'timeline', +} + +export enum ProductFeatureNotesFeatureKey { + /** + * Enables Notes + */ + notes = 'notes', +} + // Merges the two enums. export const ProductFeatureKey = { ...ProductFeatureSecurityKey, ...ProductFeatureCasesKey, ...ProductFeatureAssistantKey, ...ProductFeatureAttackDiscoveryKey, + ...ProductFeatureTimelineFeatureKey, + ...ProductFeatureNotesFeatureKey, }; // We need to merge the value and the type and export both to replicate how enum works. export type ProductFeatureKeyType = | ProductFeatureSecurityKey | ProductFeatureCasesKey | ProductFeatureAssistantKey - | ProductFeatureAttackDiscoveryKey; + | ProductFeatureAttackDiscoveryKey + | ProductFeatureTimelineFeatureKey + | ProductFeatureNotesFeatureKey; export const ALL_PRODUCT_FEATURE_KEYS = Object.freeze(Object.values(ProductFeatureKey)); diff --git a/x-pack/solutions/security/packages/features/src/security/index.ts b/x-pack/solutions/security/packages/features/src/security/index.ts index e59b0662dd975..910710a4b9f28 100644 --- a/x-pack/solutions/security/packages/features/src/security/index.ts +++ b/x-pack/solutions/security/packages/features/src/security/index.ts @@ -6,13 +6,21 @@ */ import type { SecuritySubFeatureId } from '../product_features_keys'; import type { ProductFeatureParams } from '../types'; -import { getSecurityBaseKibanaFeature } from './kibana_features'; +import { getSecurityBaseKibanaFeature } from './v1_features/kibana_features'; import { getSecuritySubFeaturesMap, getSecurityBaseKibanaSubFeatureIds, -} from './kibana_sub_features'; +} from './v1_features/kibana_sub_features'; +import { getSecurityV2BaseKibanaFeature } from './v2_features/kibana_features'; +import { + getSecurityV2SubFeaturesMap, + getSecurityV2BaseKibanaSubFeatureIds, +} from './v2_features/kibana_sub_features'; import type { SecurityFeatureParams } from './types'; +/** + * @deprecated Use getSecurityV2Feature instead + */ export const getSecurityFeature = ( params: SecurityFeatureParams ): ProductFeatureParams => ({ @@ -20,3 +28,11 @@ export const getSecurityFeature = ( baseKibanaSubFeatureIds: getSecurityBaseKibanaSubFeatureIds(params), subFeaturesMap: getSecuritySubFeaturesMap(params), }); + +export const getSecurityV2Feature = ( + params: SecurityFeatureParams +): ProductFeatureParams => ({ + baseKibanaFeature: getSecurityV2BaseKibanaFeature(params), + baseKibanaSubFeatureIds: getSecurityV2BaseKibanaSubFeatureIds(params), + subFeaturesMap: getSecurityV2SubFeaturesMap(params), +}); diff --git a/x-pack/solutions/security/packages/features/src/security/v1_features/kibana_features.ts b/x-pack/solutions/security/packages/features/src/security/v1_features/kibana_features.ts new file mode 100644 index 0000000000000..84a2f71bb32ab --- /dev/null +++ b/x-pack/solutions/security/packages/features/src/security/v1_features/kibana_features.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 { i18n } from '@kbn/i18n'; +import { KibanaFeatureScope } from '@kbn/features-plugin/common'; + +import { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; +import { + EQL_RULE_TYPE_ID, + ESQL_RULE_TYPE_ID, + INDICATOR_RULE_TYPE_ID, + ML_RULE_TYPE_ID, + NEW_TERMS_RULE_TYPE_ID, + QUERY_RULE_TYPE_ID, + SAVED_QUERY_RULE_TYPE_ID, + THRESHOLD_RULE_TYPE_ID, +} from '@kbn/securitysolution-rules'; +import { + APP_ID, + SERVER_APP_ID, + LEGACY_NOTIFICATIONS_ID, + CLOUD_POSTURE_APP_ID, + CLOUD_DEFEND_APP_ID, + SECURITY_FEATURE_ID_V2, + TIMELINE_FEATURE_ID, + NOTES_FEATURE_ID, +} from '../../constants'; +import type { SecurityFeatureParams } from '../types'; +import type { BaseKibanaFeatureConfig } from '../../types'; + +const SECURITY_RULE_TYPES = [ + LEGACY_NOTIFICATIONS_ID, + ESQL_RULE_TYPE_ID, + EQL_RULE_TYPE_ID, + INDICATOR_RULE_TYPE_ID, + ML_RULE_TYPE_ID, + QUERY_RULE_TYPE_ID, + SAVED_QUERY_RULE_TYPE_ID, + THRESHOLD_RULE_TYPE_ID, + NEW_TERMS_RULE_TYPE_ID, +]; + +const alertingFeatures = SECURITY_RULE_TYPES.map((ruleTypeId) => ({ + ruleTypeId, + consumers: [SERVER_APP_ID], +})); + +export const getSecurityBaseKibanaFeature = ({ + savedObjects, +}: SecurityFeatureParams): BaseKibanaFeatureConfig => ({ + deprecated: { + notice: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.linkSecuritySolutionSecurity.deprecationMessage', + { + defaultMessage: 'The {currentId} permissions are deprecated, please see {idV2}.', + values: { + currentId: SERVER_APP_ID, + idV2: SECURITY_FEATURE_ID_V2, + }, + } + ), + }, + + id: SERVER_APP_ID, + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.linkSecuritySolutionTitleDeprecated', + { + defaultMessage: 'Security (Deprecated)', + } + ), + order: 1100, + category: DEFAULT_APP_CATEGORIES.security, + scope: [KibanaFeatureScope.Spaces, KibanaFeatureScope.Security], + app: [APP_ID, CLOUD_POSTURE_APP_ID, CLOUD_DEFEND_APP_ID, 'kibana'], + catalogue: [APP_ID], + management: { + insightsAndAlerting: ['triggersActions'], + }, + alerting: alertingFeatures, + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.securityGroupDescription', + { + defaultMessage: + "Each sub-feature privilege in this group must be assigned individually. Global assignment is only supported if your pricing plan doesn't allow individual feature privileges.", + } + ), + privileges: { + all: { + replacedBy: { + default: [ + { feature: TIMELINE_FEATURE_ID, privileges: ['all'] }, + { feature: NOTES_FEATURE_ID, privileges: ['all'] }, + { feature: SECURITY_FEATURE_ID_V2, privileges: ['all'] }, + ], + minimal: [ + { feature: TIMELINE_FEATURE_ID, privileges: ['all'] }, + { feature: NOTES_FEATURE_ID, privileges: ['all'] }, + { feature: SECURITY_FEATURE_ID_V2, privileges: ['minimal_all'] }, + ], + }, + app: [APP_ID, CLOUD_POSTURE_APP_ID, CLOUD_DEFEND_APP_ID, 'kibana'], + catalogue: [APP_ID], + api: [ + APP_ID, + 'lists-all', + 'lists-read', + 'lists-summary', + 'rac', + 'cloud-security-posture-all', + 'cloud-security-posture-read', + 'cloud-defend-all', + 'cloud-defend-read', + 'timeline_write', + 'timeline_read', + 'notes_write', + 'notes_read', + ], + savedObject: { + all: ['alert', ...savedObjects], + read: [], + }, + alerting: { + rule: { + all: alertingFeatures, + }, + alert: { + all: alertingFeatures, + }, + }, + management: { + insightsAndAlerting: ['triggersActions'], + }, + ui: ['show', 'crud'], + }, + read: { + replacedBy: { + default: [ + { feature: TIMELINE_FEATURE_ID, privileges: ['read'] }, + { feature: NOTES_FEATURE_ID, privileges: ['read'] }, + { feature: SECURITY_FEATURE_ID_V2, privileges: ['read'] }, + ], + minimal: [ + { feature: TIMELINE_FEATURE_ID, privileges: ['read'] }, + { feature: NOTES_FEATURE_ID, privileges: ['read'] }, + { feature: SECURITY_FEATURE_ID_V2, privileges: ['minimal_read'] }, + ], + }, + app: [APP_ID, CLOUD_POSTURE_APP_ID, CLOUD_DEFEND_APP_ID, 'kibana'], + catalogue: [APP_ID], + api: [ + APP_ID, + 'lists-read', + 'rac', + 'cloud-security-posture-read', + 'cloud-defend-read', + 'timeline_read', + 'notes_read', + ], + savedObject: { + all: [], + read: [...savedObjects], + }, + alerting: { + rule: { + read: alertingFeatures, + }, + alert: { + all: alertingFeatures, + }, + }, + management: { + insightsAndAlerting: ['triggersActions'], + }, + ui: ['show'], + }, + }, +}); diff --git a/x-pack/solutions/security/packages/features/src/security/v1_features/kibana_sub_features.ts b/x-pack/solutions/security/packages/features/src/security/v1_features/kibana_sub_features.ts new file mode 100644 index 0000000000000..8d3c9b4a36a2c --- /dev/null +++ b/x-pack/solutions/security/packages/features/src/security/v1_features/kibana_sub_features.ts @@ -0,0 +1,755 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; +import type { SubFeatureConfig } from '@kbn/features-plugin/common'; +import { EXCEPTION_LIST_NAMESPACE_AGNOSTIC } from '@kbn/securitysolution-list-constants'; +import { + ProductFeaturesPrivilegeId, + ProductFeaturesPrivileges, +} from '../../product_features_privileges'; + +import { SecuritySubFeatureId } from '../../product_features_keys'; +import { APP_ID, SECURITY_FEATURE_ID_V2 } from '../../constants'; +import type { SecurityFeatureParams } from '../types'; + +const endpointListSubFeature = (): SubFeatureConfig => ({ + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.endpointList.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Endpoint List access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.endpointList', + { + defaultMessage: 'Endpoint List', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.endpointList.description', + { + defaultMessage: + 'Displays all hosts running Elastic Defend and their relevant integration details.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + replacedBy: [{ feature: SECURITY_FEATURE_ID_V2, privileges: ['endpoint_list_all'] }], + api: [`${APP_ID}-writeEndpointList`, `${APP_ID}-readEndpointList`], + id: 'endpoint_list_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [], + read: [], + }, + ui: ['writeEndpointList', 'readEndpointList'], + }, + { + replacedBy: [{ feature: SECURITY_FEATURE_ID_V2, privileges: ['endpoint_list_read'] }], + api: [`${APP_ID}-readEndpointList`], + id: 'endpoint_list_read', + includeIn: 'none', + name: 'Read', + savedObject: { + all: [], + read: [], + }, + ui: ['readEndpointList'], + }, + ], + }, + ], +}); + +const trustedApplicationsSubFeature = (): SubFeatureConfig => ({ + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Trusted Applications access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications', + { + defaultMessage: 'Trusted Applications', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications.description', + { + defaultMessage: + 'Helps mitigate conflicts with other software, usually other antivirus or endpoint security applications.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + replacedBy: [ + { feature: SECURITY_FEATURE_ID_V2, privileges: ['trusted_applications_all'] }, + ], + api: [ + 'lists-all', + 'lists-read', + 'lists-summary', + `${APP_ID}-writeTrustedApplications`, + `${APP_ID}-readTrustedApplications`, + ], + id: 'trusted_applications_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [EXCEPTION_LIST_NAMESPACE_AGNOSTIC], + read: [], + }, + ui: ['writeTrustedApplications', 'readTrustedApplications'], + }, + { + replacedBy: [ + { feature: SECURITY_FEATURE_ID_V2, privileges: ['trusted_applications_read'] }, + ], + api: ['lists-read', 'lists-summary', `${APP_ID}-readTrustedApplications`], + id: 'trusted_applications_read', + includeIn: 'none', + name: 'Read', + savedObject: { + all: [], + read: [], + }, + ui: ['readTrustedApplications'], + }, + ], + }, + ], +}); +const hostIsolationExceptionsBasicSubFeature = (): SubFeatureConfig => ({ + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.hostIsolationExceptions.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Host Isolation Exceptions access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.hostIsolationExceptions', + { + defaultMessage: 'Host Isolation Exceptions', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.hostIsolationExceptions.description', + { + defaultMessage: + 'Add specific IP addresses that isolated hosts are still allowed to communicate with, even when isolated from the rest of the network.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + replacedBy: [ + { feature: SECURITY_FEATURE_ID_V2, privileges: ['host_isolation_exceptions_all'] }, + ], + api: [ + 'lists-all', + 'lists-read', + 'lists-summary', + `${APP_ID}-deleteHostIsolationExceptions`, + `${APP_ID}-readHostIsolationExceptions`, + ], + id: 'host_isolation_exceptions_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [EXCEPTION_LIST_NAMESPACE_AGNOSTIC], + read: [], + }, + ui: ['readHostIsolationExceptions', 'deleteHostIsolationExceptions'], + }, + { + replacedBy: [ + { feature: SECURITY_FEATURE_ID_V2, privileges: ['host_isolation_exceptions_read'] }, + ], + api: ['lists-read', 'lists-summary', `${APP_ID}-readHostIsolationExceptions`], + id: 'host_isolation_exceptions_read', + includeIn: 'none', + name: 'Read', + savedObject: { + all: [], + read: [], + }, + ui: ['readHostIsolationExceptions'], + }, + ], + }, + ], +}); +const blocklistSubFeature = (): SubFeatureConfig => ({ + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.blockList.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Blocklist access.', + } + ), + name: i18n.translate('securitySolutionPackages.features.featureRegistry.subFeatures.blockList', { + defaultMessage: 'Blocklist', + }), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.blockList.description', + { + defaultMessage: + 'Extend Elastic Defend’s protection against malicious processes and protect against potentially harmful applications.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + replacedBy: [{ feature: SECURITY_FEATURE_ID_V2, privileges: ['blocklist_all'] }], + api: [ + 'lists-all', + 'lists-read', + 'lists-summary', + `${APP_ID}-writeBlocklist`, + `${APP_ID}-readBlocklist`, + ], + id: 'blocklist_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [EXCEPTION_LIST_NAMESPACE_AGNOSTIC], + read: [], + }, + ui: ['writeBlocklist', 'readBlocklist'], + }, + { + replacedBy: [{ feature: SECURITY_FEATURE_ID_V2, privileges: ['blocklist_read'] }], + api: ['lists-read', 'lists-summary', `${APP_ID}-readBlocklist`], + id: 'blocklist_read', + includeIn: 'none', + name: 'Read', + savedObject: { + all: [], + read: [], + }, + ui: ['readBlocklist'], + }, + ], + }, + ], +}); +const eventFiltersSubFeature = (): SubFeatureConfig => ({ + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.eventFilters.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Event Filters access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.eventFilters', + { + defaultMessage: 'Event Filters', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.eventFilters.description', + { + defaultMessage: + 'Filter out endpoint events that you do not need or want stored in Elasticsearch.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + replacedBy: [{ feature: SECURITY_FEATURE_ID_V2, privileges: ['event_filters_all'] }], + api: [ + 'lists-all', + 'lists-read', + 'lists-summary', + `${APP_ID}-writeEventFilters`, + `${APP_ID}-readEventFilters`, + ], + id: 'event_filters_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [EXCEPTION_LIST_NAMESPACE_AGNOSTIC], + read: [], + }, + ui: ['writeEventFilters', 'readEventFilters'], + }, + { + replacedBy: [{ feature: SECURITY_FEATURE_ID_V2, privileges: ['event_filters_read'] }], + api: ['lists-read', 'lists-summary', `${APP_ID}-readEventFilters`], + id: 'event_filters_read', + includeIn: 'none', + name: 'Read', + savedObject: { + all: [], + read: [], + }, + ui: ['readEventFilters'], + }, + ], + }, + ], +}); +const policyManagementSubFeature = (): SubFeatureConfig => ({ + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.policyManagement.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Policy Management access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.policyManagement', + { + defaultMessage: 'Elastic Defend Policy Management', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.policyManagement.description', + { + defaultMessage: + 'Access the Elastic Defend integration policy to configure protections, event collection, and advanced policy features.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + replacedBy: [{ feature: SECURITY_FEATURE_ID_V2, privileges: ['policy_management_all'] }], + api: [`${APP_ID}-writePolicyManagement`, `${APP_ID}-readPolicyManagement`], + id: 'policy_management_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: ['policy-settings-protection-updates-note'], + read: [], + }, + ui: ['writePolicyManagement', 'readPolicyManagement'], + }, + { + replacedBy: [{ feature: SECURITY_FEATURE_ID_V2, privileges: ['policy_management_read'] }], + api: [`${APP_ID}-readPolicyManagement`], + id: 'policy_management_read', + includeIn: 'none', + name: 'Read', + savedObject: { + all: [], + read: ['policy-settings-protection-updates-note'], + }, + ui: ['readPolicyManagement'], + }, + ], + }, + ], +}); + +const responseActionsHistorySubFeature = (): SubFeatureConfig => ({ + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.responseActionsHistory.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Response Actions History access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.responseActionsHistory', + { + defaultMessage: 'Response Actions History', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.responseActionsHistory.description', + { + defaultMessage: 'Access the history of response actions performed on endpoints.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + replacedBy: [ + { feature: SECURITY_FEATURE_ID_V2, privileges: ['actions_log_management_all'] }, + ], + api: [`${APP_ID}-writeActionsLogManagement`, `${APP_ID}-readActionsLogManagement`], + id: 'actions_log_management_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [], + read: [], + }, + ui: ['writeActionsLogManagement', 'readActionsLogManagement'], + }, + { + replacedBy: [ + { feature: SECURITY_FEATURE_ID_V2, privileges: ['actions_log_management_read'] }, + ], + api: [`${APP_ID}-readActionsLogManagement`], + id: 'actions_log_management_read', + includeIn: 'none', + name: 'Read', + savedObject: { + all: [], + read: [], + }, + ui: ['readActionsLogManagement'], + }, + ], + }, + ], +}); +const hostIsolationSubFeature = (): SubFeatureConfig => ({ + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.hostIsolation.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Host Isolation access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.hostIsolation', + { + defaultMessage: 'Host Isolation', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.hostIsolation.description', + { defaultMessage: 'Perform the "isolate" and "release" response actions.' } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + replacedBy: [{ feature: SECURITY_FEATURE_ID_V2, privileges: ['host_isolation_all'] }], + api: [`${APP_ID}-writeHostIsolationRelease`], + id: 'host_isolation_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [], + read: [], + }, + ui: ['writeHostIsolationRelease'], + }, + ], + }, + ], +}); + +const processOperationsSubFeature = (): SubFeatureConfig => ({ + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.processOperations.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Process Operations access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.processOperations', + { + defaultMessage: 'Process Operations', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.processOperations.description', + { + defaultMessage: 'Perform process-related response actions in the response console.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + replacedBy: [{ feature: SECURITY_FEATURE_ID_V2, privileges: ['process_operations_all'] }], + api: [`${APP_ID}-writeProcessOperations`], + id: 'process_operations_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [], + read: [], + }, + ui: ['writeProcessOperations'], + }, + ], + }, + ], +}); +const fileOperationsSubFeature = (): SubFeatureConfig => ({ + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.fileOperations.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for File Operations access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.fileOperations', + { + defaultMessage: 'File Operations', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.fileOperations.description', + { + defaultMessage: 'Perform file-related response actions in the response console.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + replacedBy: [{ feature: SECURITY_FEATURE_ID_V2, privileges: ['file_operations_all'] }], + api: [`${APP_ID}-writeFileOperations`], + id: 'file_operations_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [], + read: [], + }, + ui: ['writeFileOperations'], + }, + ], + }, + ], +}); + +// execute operations are not available in 8.7, +// but will be available in 8.8 +const executeActionSubFeature = (): SubFeatureConfig => ({ + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.executeOperations.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Execute Operations access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.executeOperations', + { + defaultMessage: 'Execute Operations', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.executeOperations.description', + { + defaultMessage: 'Perform script execution response actions in the response console.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + replacedBy: [{ feature: SECURITY_FEATURE_ID_V2, privileges: ['execute_operations_all'] }], + api: [`${APP_ID}-writeExecuteOperations`], + id: 'execute_operations_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [], + read: [], + }, + ui: ['writeExecuteOperations'], + }, + ], + }, + ], +}); + +// 8.15 feature +const scanActionSubFeature = (): SubFeatureConfig => ({ + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.scanOperations.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Scan Operations access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.scanOperations', + { + defaultMessage: 'Scan Operations', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.scanOperations.description', + { + defaultMessage: 'Perform folder scan response actions in the response console.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + replacedBy: [{ feature: SECURITY_FEATURE_ID_V2, privileges: ['scan_operations_all'] }], + + api: [`${APP_ID}-writeScanOperations`], + id: 'scan_operations_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [], + read: [], + }, + ui: ['writeScanOperations'], + }, + ], + }, + ], +}); + +const endpointExceptionsSubFeature = (): SubFeatureConfig => ({ + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.endpointExceptions.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Endpoint Exceptions access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.endpointExceptions', + { + defaultMessage: 'Endpoint Exceptions', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.endpointExceptions.description', + { + defaultMessage: 'Use Endpoint Exceptions (this is a test sub-feature).', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + replacedBy: [ + { feature: SECURITY_FEATURE_ID_V2, privileges: ['endpoint_exceptions_all'] }, + ], + id: 'endpoint_exceptions_all', + includeIn: 'all', + name: 'All', + savedObject: { + all: [], + read: [], + }, + ...ProductFeaturesPrivileges[ProductFeaturesPrivilegeId.endpointExceptions].all, + }, + { + replacedBy: [ + { feature: SECURITY_FEATURE_ID_V2, privileges: ['endpoint_exceptions_read'] }, + ], + id: 'endpoint_exceptions_read', + includeIn: 'read', + name: 'Read', + savedObject: { + all: [], + read: [], + }, + ...ProductFeaturesPrivileges[ProductFeaturesPrivilegeId.endpointExceptions].read, + }, + ], + }, + ], +}); + +/** + * Sub-features that will always be available for Security + * regardless of the product type. + */ +export const getSecurityBaseKibanaSubFeatureIds = ( + { experimentalFeatures }: SecurityFeatureParams // currently un-used, but left here as a convenience for possible future use +): SecuritySubFeatureId[] => [SecuritySubFeatureId.hostIsolation]; + +/** + * Defines all the Security Assistant subFeatures available. + * The order of the subFeatures is the order they will be displayed + */ + +export const getSecuritySubFeaturesMap = ({ + experimentalFeatures, +}: SecurityFeatureParams): Map => { + const enableSpaceAwarenessIfNeeded = (subFeature: SubFeatureConfig): SubFeatureConfig => { + if (experimentalFeatures.endpointManagementSpaceAwarenessEnabled) { + subFeature.requireAllSpaces = false; + subFeature.privilegesTooltip = undefined; + } + + return subFeature; + }; + + const securitySubFeaturesList: Array<[SecuritySubFeatureId, SubFeatureConfig]> = [ + [SecuritySubFeatureId.endpointList, enableSpaceAwarenessIfNeeded(endpointListSubFeature())], + [ + SecuritySubFeatureId.endpointExceptions, + enableSpaceAwarenessIfNeeded(endpointExceptionsSubFeature()), + ], + [ + SecuritySubFeatureId.trustedApplications, + enableSpaceAwarenessIfNeeded(trustedApplicationsSubFeature()), + ], + [ + SecuritySubFeatureId.hostIsolationExceptionsBasic, + enableSpaceAwarenessIfNeeded(hostIsolationExceptionsBasicSubFeature()), + ], + [SecuritySubFeatureId.blocklist, enableSpaceAwarenessIfNeeded(blocklistSubFeature())], + [SecuritySubFeatureId.eventFilters, enableSpaceAwarenessIfNeeded(eventFiltersSubFeature())], + [ + SecuritySubFeatureId.policyManagement, + enableSpaceAwarenessIfNeeded(policyManagementSubFeature()), + ], + [ + SecuritySubFeatureId.responseActionsHistory, + enableSpaceAwarenessIfNeeded(responseActionsHistorySubFeature()), + ], + [SecuritySubFeatureId.hostIsolation, enableSpaceAwarenessIfNeeded(hostIsolationSubFeature())], + [ + SecuritySubFeatureId.processOperations, + enableSpaceAwarenessIfNeeded(processOperationsSubFeature()), + ], + [SecuritySubFeatureId.fileOperations, enableSpaceAwarenessIfNeeded(fileOperationsSubFeature())], + [SecuritySubFeatureId.executeAction, enableSpaceAwarenessIfNeeded(executeActionSubFeature())], + [SecuritySubFeatureId.scanAction, enableSpaceAwarenessIfNeeded(scanActionSubFeature())], + ]; + + // Use the following code to add feature based on feature flag + // if (experimentalFeatures.featureFlagName) { + // securitySubFeaturesList.push([SecuritySubFeatureId.featureId, featureSubFeature]); + // } + + const securitySubFeaturesMap = new Map( + securitySubFeaturesList + ); + + return Object.freeze(securitySubFeaturesMap); +}; diff --git a/x-pack/solutions/security/packages/features/src/security/kibana_features.ts b/x-pack/solutions/security/packages/features/src/security/v2_features/kibana_features.ts similarity index 93% rename from x-pack/solutions/security/packages/features/src/security/kibana_features.ts rename to x-pack/solutions/security/packages/features/src/security/v2_features/kibana_features.ts index 458b8f6fd1f1f..1037cd356699e 100644 --- a/x-pack/solutions/security/packages/features/src/security/kibana_features.ts +++ b/x-pack/solutions/security/packages/features/src/security/v2_features/kibana_features.ts @@ -19,15 +19,16 @@ import { SAVED_QUERY_RULE_TYPE_ID, THRESHOLD_RULE_TYPE_ID, } from '@kbn/securitysolution-rules'; -import type { BaseKibanaFeatureConfig } from '../types'; import { APP_ID, - SERVER_APP_ID, + SECURITY_FEATURE_ID_V2, LEGACY_NOTIFICATIONS_ID, CLOUD_POSTURE_APP_ID, CLOUD_DEFEND_APP_ID, -} from '../constants'; -import type { SecurityFeatureParams } from './types'; + SERVER_APP_ID, +} from '../../constants'; +import type { SecurityFeatureParams } from '../types'; +import type { BaseKibanaFeatureConfig } from '../../types'; const SECURITY_RULE_TYPES = [ LEGACY_NOTIFICATIONS_ID, @@ -46,10 +47,10 @@ const alertingFeatures = SECURITY_RULE_TYPES.map((ruleTypeId) => ({ consumers: [SERVER_APP_ID], })); -export const getSecurityBaseKibanaFeature = ({ +export const getSecurityV2BaseKibanaFeature = ({ savedObjects, }: SecurityFeatureParams): BaseKibanaFeatureConfig => ({ - id: SERVER_APP_ID, + id: SECURITY_FEATURE_ID_V2, name: i18n.translate( 'securitySolutionPackages.features.featureRegistry.linkSecuritySolutionTitle', { diff --git a/x-pack/solutions/security/packages/features/src/security/kibana_sub_features.ts b/x-pack/solutions/security/packages/features/src/security/v2_features/kibana_sub_features.ts similarity index 98% rename from x-pack/solutions/security/packages/features/src/security/kibana_sub_features.ts rename to x-pack/solutions/security/packages/features/src/security/v2_features/kibana_sub_features.ts index 51e15f67433dd..d4a20c92bc74c 100644 --- a/x-pack/solutions/security/packages/features/src/security/kibana_sub_features.ts +++ b/x-pack/solutions/security/packages/features/src/security/v2_features/kibana_sub_features.ts @@ -11,11 +11,11 @@ import { EXCEPTION_LIST_NAMESPACE_AGNOSTIC } from '@kbn/securitysolution-list-co import { ProductFeaturesPrivilegeId, ProductFeaturesPrivileges, -} from '../product_features_privileges'; +} from '../../product_features_privileges'; -import { SecuritySubFeatureId } from '../product_features_keys'; -import { APP_ID } from '../constants'; -import type { SecurityFeatureParams } from './types'; +import { SecuritySubFeatureId } from '../../product_features_keys'; +import { APP_ID } from '../../constants'; +import type { SecurityFeatureParams } from '../types'; const endpointListSubFeature = (): SubFeatureConfig => ({ requireAllSpaces: true, @@ -701,7 +701,7 @@ const endpointExceptionsSubFeature = (): SubFeatureConfig => ({ * Sub-features that will always be available for Security * regardless of the product type. */ -export const getSecurityBaseKibanaSubFeatureIds = ( +export const getSecurityV2BaseKibanaSubFeatureIds = ( { experimentalFeatures }: SecurityFeatureParams // currently un-used, but left here as a convenience for possible future use ): SecuritySubFeatureId[] => [SecuritySubFeatureId.hostIsolation]; @@ -710,7 +710,7 @@ export const getSecurityBaseKibanaSubFeatureIds = ( * The order of the subFeatures is the order they will be displayed */ -export const getSecuritySubFeaturesMap = ({ +export const getSecurityV2SubFeaturesMap = ({ experimentalFeatures, }: SecurityFeatureParams): Map => { const enableSpaceAwarenessIfNeeded = (subFeature: SubFeatureConfig): SubFeatureConfig => { diff --git a/x-pack/solutions/security/packages/features/src/timeline/index.ts b/x-pack/solutions/security/packages/features/src/timeline/index.ts new file mode 100644 index 0000000000000..62042881ec6f2 --- /dev/null +++ b/x-pack/solutions/security/packages/features/src/timeline/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getTimelineBaseKibanaFeature } from './kibana_features'; +import type { ProductFeatureParams } from '../types'; +import type { SecurityFeatureParams } from '../security/types'; + +export const getTimelineFeature = (params: SecurityFeatureParams): ProductFeatureParams => ({ + baseKibanaFeature: getTimelineBaseKibanaFeature(params), + baseKibanaSubFeatureIds: [], + subFeaturesMap: new Map(), +}); diff --git a/x-pack/solutions/security/packages/features/src/timeline/kibana_features.ts b/x-pack/solutions/security/packages/features/src/timeline/kibana_features.ts new file mode 100644 index 0000000000000..5c9fbfecda570 --- /dev/null +++ b/x-pack/solutions/security/packages/features/src/timeline/kibana_features.ts @@ -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 { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; +import { i18n } from '@kbn/i18n'; +import { KibanaFeatureScope } from '@kbn/features-plugin/common'; + +import { APP_ID, TIMELINE_FEATURE_ID } from '../constants'; +import { type BaseKibanaFeatureConfig } from '../types'; +import type { SecurityFeatureParams } from '../security/types'; + +export const getTimelineBaseKibanaFeature = ( + params: SecurityFeatureParams +): BaseKibanaFeatureConfig => ({ + id: TIMELINE_FEATURE_ID, + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.linkSecuritySolutionTimelineTitle', + { + defaultMessage: 'Timeline', + } + ), + order: 1100, + category: DEFAULT_APP_CATEGORIES.security, + scope: [KibanaFeatureScope.Spaces, KibanaFeatureScope.Security], + app: [TIMELINE_FEATURE_ID, 'kibana'], + catalogue: [APP_ID], + privileges: { + all: { + app: [TIMELINE_FEATURE_ID, 'kibana'], + catalogue: [APP_ID], + savedObject: { + all: params.savedObjects, + read: params.savedObjects, + }, + ui: ['read', 'crud'], + api: ['timeline_read', 'timeline_write'], + }, + read: { + app: [TIMELINE_FEATURE_ID, 'kibana'], + catalogue: [APP_ID], + savedObject: { + all: [], + read: params.savedObjects, + }, + ui: ['read'], + api: ['timeline_read'], + }, + }, +}); diff --git a/x-pack/solutions/security/packages/features/src/timeline/product_feature_config.ts b/x-pack/solutions/security/packages/features/src/timeline/product_feature_config.ts new file mode 100644 index 0000000000000..dd442014bf6fe --- /dev/null +++ b/x-pack/solutions/security/packages/features/src/timeline/product_feature_config.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 { ProductFeatureTimelineFeatureKey } from '../product_features_keys'; +import type { ProductFeatureKibanaConfig } from '../types'; + +/** + * App features privileges configuration for the timeline feature. + * These are the configs that are shared between both offering types (ess and serverless). + * They can be extended on each offering plugin to register privileges using different way on each offering type. + * + * Privileges can be added in different ways: + * - `privileges`: the privileges that will be added directly into the main Security feature. + * - `subFeatureIds`: the ids of the sub-features that will be added into the Security subFeatures entry. + * - `subFeaturesPrivileges`: the privileges that will be added into the existing Security subFeature with the privilege `id` specified. + */ +export const timelineDefaultProductFeaturesConfig: Record< + ProductFeatureTimelineFeatureKey, + ProductFeatureKibanaConfig +> = { + [ProductFeatureTimelineFeatureKey.timeline]: { + privileges: { + all: { + api: ['timeline_read', 'timeline_write'], + ui: ['read', 'crud'], + }, + read: { + api: ['timeline_read'], + ui: ['read'], + }, + }, + }, +}; diff --git a/x-pack/solutions/security/packages/features/src/types.ts b/x-pack/solutions/security/packages/features/src/types.ts index 17e4869fa66f1..e180851a62cee 100644 --- a/x-pack/solutions/security/packages/features/src/types.ts +++ b/x-pack/solutions/security/packages/features/src/types.ts @@ -20,6 +20,8 @@ import type { AssistantSubFeatureId, CasesSubFeatureId, SecuritySubFeatureId, + ProductFeatureTimelineFeatureKey, + ProductFeatureNotesFeatureKey, } from './product_features_keys'; export type { ProductFeatureKeyType }; @@ -57,6 +59,16 @@ export type ProductFeaturesAttackDiscoveryConfig = Map< ProductFeatureKibanaConfig >; +export type ProductFeaturesTimelineConfig = Map< + ProductFeatureTimelineFeatureKey, + ProductFeatureKibanaConfig +>; + +export type ProductFeaturesNotesConfig = Map< + ProductFeatureNotesFeatureKey, + ProductFeatureKibanaConfig +>; + export type AppSubFeaturesMap = Map; export interface ProductFeatureParams { diff --git a/x-pack/solutions/security/packages/kbn-cloud-security-posture/graph/src/components/graph_investigation/graph_investigation.stories.test.tsx b/x-pack/solutions/security/packages/kbn-cloud-security-posture/graph/src/components/graph_investigation/graph_investigation.stories.test.tsx index a4f3728c94eb7..02cc3679ce248 100644 --- a/x-pack/solutions/security/packages/kbn-cloud-security-posture/graph/src/components/graph_investigation/graph_investigation.stories.test.tsx +++ b/x-pack/solutions/security/packages/kbn-cloud-security-posture/graph/src/components/graph_investigation/graph_investigation.stories.test.tsx @@ -112,7 +112,8 @@ const isSearchBarVisible = (container: HTMLElement) => { return searchBarContainer === null; }; -describe('GraphInvestigation Component', () => { +// FLAKY: https://github.com/elastic/kibana/issues/206646 +describe.skip('GraphInvestigation Component', () => { beforeEach(() => { for (const key in actionMocks) { if (Object.prototype.hasOwnProperty.call(actionMocks, key)) { diff --git a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/index.ts b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/index.ts index bf4bccda2816e..59d1ca5fb1f43 100644 --- a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/index.ts +++ b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/index.ts @@ -6,13 +6,16 @@ */ export * from './src/types'; -export * from './src/constants/component_constants'; export * from './src/constants/navigation'; export type { NavFilter } from './src/utils/query_utils'; export { showErrorToast } from './src/utils/show_error_toast'; export { encodeQuery, decodeQuery } from './src/utils/query_utils'; export { CspEvaluationBadge } from './src/components/csp_evaluation_badge'; -export { getSeverityStatusColor, getCvsScoreColor } from './src/utils/get_vulnerability_colors'; +export { + getSeverityStatusColor, + getCvsScoreColor, + getMisconfigurationStatusColor, +} from './src/utils/get_finding_colors'; export { getSeverityText } from './src/utils/get_vulnerability_text'; export { getVulnerabilityStats, hasVulnerabilitiesData } from './src/utils/vulnerability_helpers'; export { CVSScoreBadge, SeverityStatusBadge } from './src/components/vulnerability_badges'; diff --git a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/components/csp_evaluation_badge.tsx b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/components/csp_evaluation_badge.tsx index 28a5b7655723a..f185091dbf5de 100644 --- a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/components/csp_evaluation_badge.tsx +++ b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/components/csp_evaluation_badge.tsx @@ -6,28 +6,24 @@ */ import React from 'react'; -import { EuiBadge, type EuiBadgeProps } from '@elastic/eui'; +import { EuiBadge } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { css } from '@emotion/react'; -import { statusColors } from '../constants/component_constants'; +import { MISCONFIGURATION_STATUS } from '@kbn/cloud-security-posture-common'; +import type { MisconfigurationEvaluationStatus } from '@kbn/cloud-security-posture-common'; +import { getMisconfigurationStatusColor } from '../utils/get_finding_colors'; interface Props { - type?: 'passed' | 'failed'; + type?: MisconfigurationEvaluationStatus; } // 'fail' / 'pass' are same chars length, but not same width size. // 46px is used to make sure the badge is always the same width. const BADGE_WIDTH = '46px'; -const getColor = (type: Props['type']): EuiBadgeProps['color'] => { - if (type === 'passed') return statusColors.passed; - if (type === 'failed') return statusColors.failed; - return 'default'; -}; - export const CspEvaluationBadge = ({ type }: Props) => ( ( `} data-test-subj={`${type}_finding`} > - {type === 'failed' ? ( + {type === MISCONFIGURATION_STATUS.FAILED ? ( - ) : type === 'passed' ? ( + ) : type === MISCONFIGURATION_STATUS.PASSED ? ( { + const { euiTheme } = useEuiTheme(); + const { getCvsScoreColor } = useGetCvsScoreColor(); + if (!score) return null; const color = getCvsScoreColor(score); @@ -48,7 +52,7 @@ export const CVSScoreBadge = ({ score, version }: CVSScoreBadgeProps) => { css={css` width: 1px; border: 0 none; - background-color: rgba(255, 255, 255, 0.2); + background-color: ${euiTheme.border.color}; margin: 0px 6px; `} /> @@ -60,6 +64,8 @@ export const CVSScoreBadge = ({ score, version }: CVSScoreBadgeProps) => { }; export const SeverityStatusBadge = ({ severity }: SeverityStatusBadgeProps) => { + const { getSeverityStatusColor } = useGetSeverityStatusColor(); + if (!severity) return null; const color = getSeverityStatusColor(severity); diff --git a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/constants/component_constants.ts b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/constants/component_constants.ts deleted file mode 100644 index 3e22fdea80666..0000000000000 --- a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/constants/component_constants.ts +++ /dev/null @@ -1,16 +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 { euiThemeVars } from '@kbn/ui-theme'; - -export const statusColors = { - passed: euiThemeVars.euiColorSuccess, - failed: euiThemeVars.euiColorVis9, - unknown: euiThemeVars.euiColorLightShade, -}; - -export const HOST_NAME = 'host.name'; -export const USER_NAME = 'user.name'; diff --git a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/hooks/use_get_cvs_score_color.ts b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/hooks/use_get_cvs_score_color.ts new file mode 100644 index 0000000000000..f013706d0b324 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/hooks/use_get_cvs_score_color.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 { useEuiTheme } from '@elastic/eui'; + +import { getCvsScoreColor as getCvsScoreColorUtil } from '../..'; + +export const useGetCvsScoreColor = () => { + const { euiTheme } = useEuiTheme(); + + const getCvsScoreColor = (score: number) => { + return getCvsScoreColorUtil(score, euiTheme); + }; + + return { getCvsScoreColor }; +}; diff --git a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/hooks/use_get_severity_status_color.ts b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/hooks/use_get_severity_status_color.ts new file mode 100644 index 0000000000000..5a8435d6e924d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/hooks/use_get_severity_status_color.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useEuiTheme } from '@elastic/eui'; +import { VulnSeverity } from '@kbn/cloud-security-posture-common'; + +import { getSeverityStatusColor as getSeverityStatusColorUtil } from '../..'; + +export const useGetSeverityStatusColor = () => { + const { euiTheme } = useEuiTheme(); + const getSeverityStatusColor = (status: VulnSeverity) => { + return getSeverityStatusColorUtil(status, euiTheme); + }; + return { getSeverityStatusColor }; +}; diff --git a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/hooks/use_has_misconfigurations.ts b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/hooks/use_has_misconfigurations.ts index c8e36898fed16..3647c0d4de7ba 100644 --- a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/hooks/use_has_misconfigurations.ts +++ b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/hooks/use_has_misconfigurations.ts @@ -8,7 +8,7 @@ import { buildGenericEntityFlyoutPreviewQuery } from '@kbn/cloud-security-posture-common'; import { useMisconfigurationPreview } from './use_misconfiguration_preview'; -export const useHasMisconfigurations = (field: 'host.name' | 'user.name', value: string) => { +export const useHasMisconfigurations = (field: string, value: string) => { const { data } = useMisconfigurationPreview({ query: buildGenericEntityFlyoutPreviewQuery(field, value), sort: [], diff --git a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/hooks/use_has_vulnerabilities.ts b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/hooks/use_has_vulnerabilities.ts index ae7e951ce9313..c6bfe58f7a02b 100644 --- a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/hooks/use_has_vulnerabilities.ts +++ b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/hooks/use_has_vulnerabilities.ts @@ -9,7 +9,7 @@ import { buildGenericEntityFlyoutPreviewQuery } from '@kbn/cloud-security-postur import { useVulnerabilitiesPreview } from './use_vulnerabilities_preview'; import { hasVulnerabilitiesData } from '../utils/vulnerability_helpers'; -export const useHasVulnerabilities = (field: 'host.name' | 'user.name', value: string) => { +export const useHasVulnerabilities = (field: string, value: string) => { const { data: vulnerabilitiesData } = useVulnerabilitiesPreview({ query: buildGenericEntityFlyoutPreviewQuery(field, value), sort: [], diff --git a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/get_finding_colors.test.ts b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/get_finding_colors.test.ts new file mode 100644 index 0000000000000..2fa5e84c245d0 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/get_finding_colors.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 { getCvsScoreColor, getSeverityStatusColor, SEVERITY_COLOR } from './get_finding_colors'; +import { EuiThemeComputed } from '@elastic/eui'; + +const mockEuiThemeBorealis = { + themeName: 'borialis', +}; + +describe('getSeverityStatusColor', () => { + it('should return the correct color for LOW severity', () => { + expect(getSeverityStatusColor('LOW', mockEuiThemeBorealis as EuiThemeComputed)).toBe( + SEVERITY_COLOR.low + ); + }); + + it('should return the correct color for MEDIUM severity', () => { + expect(getSeverityStatusColor('MEDIUM', mockEuiThemeBorealis as EuiThemeComputed)).toBe( + SEVERITY_COLOR.medium + ); + }); + + it('should return the correct color for HIGH severity', () => { + expect(getSeverityStatusColor('HIGH', mockEuiThemeBorealis as EuiThemeComputed)).toBe( + SEVERITY_COLOR.high + ); + }); + + it('should return the correct color for CRITICAL severity', () => { + expect(getSeverityStatusColor('CRITICAL', mockEuiThemeBorealis as EuiThemeComputed)).toBe( + SEVERITY_COLOR.critical + ); + }); + + it('should return the correct color for an unknown severity', () => { + expect(getSeverityStatusColor('UNKNOWN', mockEuiThemeBorealis as EuiThemeComputed)).toBe( + SEVERITY_COLOR.unknown + ); + }); +}); + +describe('getCvsScoreColor', () => { + it('returns correct color for low severity score', () => { + expect(getCvsScoreColor(1.5, mockEuiThemeBorealis as EuiThemeComputed)).toBe( + SEVERITY_COLOR.low + ); + }); + + it('returns correct color for medium severity score', () => { + expect(getCvsScoreColor(5.5, mockEuiThemeBorealis as EuiThemeComputed)).toBe( + SEVERITY_COLOR.medium + ); + }); + + it('returns correct color for high severity score', () => { + expect(getCvsScoreColor(7.9, mockEuiThemeBorealis as EuiThemeComputed)).toBe( + SEVERITY_COLOR.high + ); + }); + + it('returns correct color for critical severity score', () => { + expect(getCvsScoreColor(10.0, mockEuiThemeBorealis as EuiThemeComputed)).toBe( + SEVERITY_COLOR.critical + ); + }); + + it('returns correct color for low severity score for undefined value', () => { + expect(getCvsScoreColor(-0.2, mockEuiThemeBorealis as EuiThemeComputed)).toBe( + SEVERITY_COLOR.unknown + ); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/get_finding_colors.ts b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/get_finding_colors.ts new file mode 100644 index 0000000000000..5209e5d766c64 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/get_finding_colors.ts @@ -0,0 +1,108 @@ +/* + * 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 { EuiThemeComputed } from '@elastic/eui'; +import { euiThemeVars } from '@kbn/ui-theme'; // TODO: replace with euiTheme +import type { + VulnSeverity, + MisconfigurationEvaluationStatus, +} from '@kbn/cloud-security-posture-common'; +import { + VULNERABILITIES_SEVERITY, + MISCONFIGURATION_STATUS, +} from '@kbn/cloud-security-posture-common'; + +const isAmsterdam = (euiThemeName: string) => { + return euiThemeName?.toLowerCase().includes('amsterdam'); +}; + +// Designers blocked the migration to tokens from EUI during the Borealys theme migration. +// We keep using hardcoded colors until security severity palette is ready https://github.com/elastic/kibana/issues/203387 +// TODO: Borealis migration - move from hardcoded values to severity palette https://github.com/elastic/security-team/issues/11606 +export const SEVERITY_COLOR = { + critical: '#E7664C', + high: '#DA8B45', + medium: '#D6BF57', + low: '#54B399', + unknown: '#aaa', +} as const; + +// TODO: Borealis migration - migrate to security severity palette when it's ready https://github.com/elastic/security-team/issues/11606 +export const getSeverityStatusColor = ( + severity: VulnSeverity, + euiTheme: EuiThemeComputed +): string => { + // TODO: Borealis migration - remove old mapping in main after Serverless switched to Borealis + if (euiTheme && isAmsterdam(euiTheme.themeName)) { + switch (severity) { + case VULNERABILITIES_SEVERITY.LOW: + return euiThemeVars.euiColorVis0; + case VULNERABILITIES_SEVERITY.MEDIUM: + return euiThemeVars.euiColorVis5_behindText; + case VULNERABILITIES_SEVERITY.HIGH: + return euiThemeVars.euiColorVis9_behindText; + case VULNERABILITIES_SEVERITY.CRITICAL: + return euiThemeVars.euiColorDanger; + default: + return '#aaa'; + } + } + + switch (severity) { + case VULNERABILITIES_SEVERITY.LOW: + return SEVERITY_COLOR.low; + case VULNERABILITIES_SEVERITY.MEDIUM: + return SEVERITY_COLOR.medium; + case VULNERABILITIES_SEVERITY.HIGH: + return SEVERITY_COLOR.high; + case VULNERABILITIES_SEVERITY.CRITICAL: + return SEVERITY_COLOR.critical; + default: + return SEVERITY_COLOR.unknown; + } +}; + +export const getCvsScoreColor = (score: number, euiTheme: EuiThemeComputed): string | undefined => { + // TODO: Borealis migration - remove old mapping in main when Serverless switched to Borealis + if (euiTheme && isAmsterdam(euiTheme.themeName)) { + if (score <= 4) { + return euiThemeVars.euiColorVis0; // low severity + } else if (score >= 4 && score <= 7) { + return euiThemeVars.euiColorVis7; // medium severity + } else if (score >= 7 && score <= 9) { + return euiThemeVars.euiColorVis9; // high severity + } else if (score >= 9) { + return euiThemeVars.euiColorDanger; // critical severity + } + } + + if (score >= 0 && score <= 4) { + return getSeverityStatusColor(VULNERABILITIES_SEVERITY.LOW, euiTheme); + } else if (score >= 4 && score <= 7) { + return getSeverityStatusColor(VULNERABILITIES_SEVERITY.MEDIUM, euiTheme); + } else if (score >= 7 && score <= 9) { + return getSeverityStatusColor(VULNERABILITIES_SEVERITY.HIGH, euiTheme); + } else if (score >= 9) { + return getSeverityStatusColor(VULNERABILITIES_SEVERITY.CRITICAL, euiTheme); + } else { + return getSeverityStatusColor(VULNERABILITIES_SEVERITY.UNKNOWN, euiTheme); + } +}; + +// TODO: Borealis migration - migrate to EUI color tokens when they are ready https://github.com/elastic/security-team/issues/11606 +export const getMisconfigurationStatusColor = ( + status?: MisconfigurationEvaluationStatus +): string => { + switch (status) { + case MISCONFIGURATION_STATUS.PASSED: + return SEVERITY_COLOR.low; + case MISCONFIGURATION_STATUS.FAILED: + return SEVERITY_COLOR.critical; + default: + return SEVERITY_COLOR.unknown; + } +}; diff --git a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/get_vulnerabilitiy_colors.test.ts b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/get_vulnerabilitiy_colors.test.ts deleted file mode 100644 index dcc506fd6b27d..0000000000000 --- a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/get_vulnerabilitiy_colors.test.ts +++ /dev/null @@ -1,52 +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 { euiThemeVars } from '@kbn/ui-theme'; -import { getCvsScoreColor, getSeverityStatusColor } from './get_vulnerability_colors'; -describe('getSeverityStatusColor', () => { - it('should return the correct color for LOW severity', () => { - expect(getSeverityStatusColor('LOW')).toBe(euiThemeVars.euiColorVis0); - }); - - it('should return the correct color for MEDIUM severity', () => { - expect(getSeverityStatusColor('MEDIUM')).toBe(euiThemeVars.euiColorVis5_behindText); - }); - - it('should return the correct color for HIGH severity', () => { - expect(getSeverityStatusColor('HIGH')).toBe(euiThemeVars.euiColorVis9_behindText); - }); - - it('should return the correct color for CRITICAL severity', () => { - expect(getSeverityStatusColor('CRITICAL')).toBe(euiThemeVars.euiColorDanger); - }); - - it('should return #aaa for an unknown severity', () => { - expect(getSeverityStatusColor('UNKNOWN')).toBe('#aaa'); - }); -}); - -describe('getCvsScoreColor', () => { - it('returns correct color for low severity score', () => { - expect(getCvsScoreColor(1.5)).toBe(euiThemeVars.euiColorVis0); - }); - - it('returns correct color for medium severity score', () => { - expect(getCvsScoreColor(5.5)).toBe(euiThemeVars.euiColorVis7); - }); - - it('returns correct color for high severity score', () => { - expect(getCvsScoreColor(7.9)).toBe(euiThemeVars.euiColorVis9); - }); - - it('returns correct color for critical severity score', () => { - expect(getCvsScoreColor(10.0)).toBe(euiThemeVars.euiColorDanger); - }); - - it('returns correct color for low severity score for undefined value', () => { - expect(getCvsScoreColor(-0.2)).toBe(euiThemeVars.euiColorVis0); - }); -}); diff --git a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/get_vulnerability_colors.ts b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/get_vulnerability_colors.ts deleted file mode 100644 index 54bcb357137b7..0000000000000 --- a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/get_vulnerability_colors.ts +++ /dev/null @@ -1,37 +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 { euiThemeVars } from '@kbn/ui-theme'; -import type { VulnSeverity } from '@kbn/cloud-security-posture-common'; -import { VULNERABILITIES_SEVERITY } from '@kbn/cloud-security-posture-common'; - -export const getCvsScoreColor = (score: number): string | undefined => { - if (score <= 4) { - return euiThemeVars.euiColorVis0; // low severity - } else if (score >= 4 && score <= 7) { - return euiThemeVars.euiColorVis7; // medium severity - } else if (score >= 7 && score <= 9) { - return euiThemeVars.euiColorVis9; // high severity - } else if (score >= 9) { - return euiThemeVars.euiColorDanger; // critical severity - } -}; - -export const getSeverityStatusColor = (severity: VulnSeverity): string => { - switch (severity) { - case VULNERABILITIES_SEVERITY.LOW: - return euiThemeVars.euiColorVis0; - case VULNERABILITIES_SEVERITY.MEDIUM: - return euiThemeVars.euiColorVis5_behindText; - case VULNERABILITIES_SEVERITY.HIGH: - return euiThemeVars.euiColorVis9_behindText; - case VULNERABILITIES_SEVERITY.CRITICAL: - return euiThemeVars.euiColorDanger; - default: - return '#aaa'; - } -}; diff --git a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/vulnerability_helpers.test.ts b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/vulnerability_helpers.test.ts index e2503b7a38a2c..afcdc331364e9 100644 --- a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/vulnerability_helpers.test.ts +++ b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/vulnerability_helpers.test.ts @@ -5,19 +5,39 @@ * 2.0. */ -import { euiThemeVars } from '@kbn/ui-theme'; -import { getVulnerabilityStats } from './vulnerability_helpers'; import { i18n } from '@kbn/i18n'; +import type { EuiThemeComputed } from '@elastic/eui'; +import type { VulnSeverity } from '@kbn/cloud-security-posture-common'; +import { getVulnerabilityStats } from './vulnerability_helpers'; +import { + getSeverityStatusColor as getSeverityStatusColorUtil, + SEVERITY_COLOR, +} from './get_finding_colors'; + +const getSeverityStatusColor = (status: VulnSeverity) => { + const euiTheme = { + themeName: 'borealis', + }; + + return getSeverityStatusColorUtil(status, euiTheme as EuiThemeComputed); +}; describe('getVulnerabilitiesAggregationCount', () => { const mockFilterFunction = jest.fn(); it('should return empty array when all severity count is 0', () => { - const result = getVulnerabilityStats({ critical: 0, high: 0, medium: 0, low: 0, none: 0 }); + const result = getVulnerabilityStats( + { critical: 0, high: 0, medium: 0, low: 0, none: 0 }, + getSeverityStatusColor + ); expect(result).toEqual([]); }); it('should return stats for low, medium, high, and critical vulnerabilities', () => { - const result = getVulnerabilityStats({ critical: 1, high: 2, medium: 3, low: 4, none: 5 }); + const result = getVulnerabilityStats( + { critical: 1, high: 2, medium: 3, low: 4, none: 5 }, + getSeverityStatusColor + ); + const resultWithoutFunctions = result.map((item) => { const { filter, reset, ...rest } = item; return rest; @@ -32,7 +52,7 @@ describe('getVulnerabilitiesAggregationCount', () => { } ), count: 5, - color: '#aaa', + color: SEVERITY_COLOR.unknown, isCurrentFilter: false, }, { @@ -43,7 +63,7 @@ describe('getVulnerabilitiesAggregationCount', () => { } ), count: 4, - color: euiThemeVars.euiColorVis0, + color: SEVERITY_COLOR.low, isCurrentFilter: false, }, { @@ -54,7 +74,7 @@ describe('getVulnerabilitiesAggregationCount', () => { } ), count: 3, - color: euiThemeVars.euiColorVis5_behindText, + color: SEVERITY_COLOR.medium, isCurrentFilter: false, }, { @@ -65,7 +85,7 @@ describe('getVulnerabilitiesAggregationCount', () => { } ), count: 2, - color: euiThemeVars.euiColorVis9_behindText, + color: SEVERITY_COLOR.high, isCurrentFilter: false, }, { @@ -76,7 +96,7 @@ describe('getVulnerabilitiesAggregationCount', () => { } ), count: 1, - color: euiThemeVars.euiColorDanger, + color: SEVERITY_COLOR.critical, isCurrentFilter: false, }, ]); @@ -85,6 +105,7 @@ describe('getVulnerabilitiesAggregationCount', () => { it('should return correct stats with correct onClick functions', () => { const result = getVulnerabilityStats( { critical: 1, high: 2, medium: 3, low: 4, none: 5 }, + getSeverityStatusColor, mockFilterFunction ); const event = { stopPropagation: jest.fn() } as unknown as React.MouseEvent< @@ -101,6 +122,7 @@ describe('getVulnerabilitiesAggregationCount', () => { const currentFilter = 'LOW'; const result = getVulnerabilityStats( { critical: 1, high: 2, medium: 3, low: 4, none: 5 }, + getSeverityStatusColor, mockFilterFunction, currentFilter ); diff --git a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/vulnerability_helpers.ts b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/vulnerability_helpers.ts index 321a135557e59..fb662c6e8e5d2 100644 --- a/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/vulnerability_helpers.ts +++ b/x-pack/solutions/security/packages/kbn-cloud-security-posture/public/src/utils/vulnerability_helpers.ts @@ -5,9 +5,8 @@ * 2.0. */ -import { VULNERABILITIES_SEVERITY } from '@kbn/cloud-security-posture-common'; +import { VULNERABILITIES_SEVERITY, VulnSeverity } from '@kbn/cloud-security-posture-common'; import { i18n } from '@kbn/i18n'; -import { getSeverityStatusColor } from './get_vulnerability_colors'; import { getSeverityText } from './get_vulnerability_text'; interface VulnerabilitiesDistributionBarProps { @@ -35,6 +34,7 @@ export const hasVulnerabilitiesData = (counts: VulnerabilityCounts): boolean => export const getVulnerabilityStats = ( counts: VulnerabilityCounts, + getSeverityStatusColor: (status: VulnSeverity) => string, filterFunction?: (filter: string) => void, currentFilter?: string ): VulnerabilitiesDistributionBarProps[] => { diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/date_math.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/date_math.ts new file mode 100644 index 0000000000000..fae52c1f7b8c9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/date_math.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './src/date_math'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/kibana.jsonc b/x-pack/solutions/security/packages/kbn-securitysolution-utils/kibana.jsonc index 5e6ccf9096ea3..a8209fee52953 100644 --- a/x-pack/solutions/security/packages/kbn-securitysolution-utils/kibana.jsonc +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/kibana.jsonc @@ -1,9 +1,7 @@ { "type": "shared-common", "id": "@kbn/securitysolution-utils", - "owner": [ - "@elastic/security-detection-engine" - ], + "owner": ["@elastic/security-detection-engine", "@elastic/security-detection-rule-management"], "group": "security", "visibility": "private" -} \ No newline at end of file +} diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/date_math/calc_date_math_diff.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/date_math/calc_date_math_diff.test.ts new file mode 100644 index 0000000000000..9cca1a0854486 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/date_math/calc_date_math_diff.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 { calcDateMathDiff } from './calc_date_math_diff'; + +describe('calcDateMathDiff', () => { + it.each([ + ['now-62s', 'now-1m', 2000], + ['now-122s', 'now-1m', 62000], + ['now-660s', 'now-5m', 360000], + ['now-6600s', 'now-5m', 6300000], + ['now-7500s', 'now-5m', 7200000], + ['now-1m', 'now-62s', -2000], + ['now-1m', 'now-122s', -62000], + ['now-5m', 'now-660s', -360000], + ['now-5m', 'now-6600s', -6300000], + ['now-5m', 'now-7500s', -7200000], + ['now-1s', 'now-1s', 0], + ['now-1m', 'now-1m', 0], + ['now-1h', 'now-1h', 0], + ['now-1d', 'now-1d', 0], + ])('calculates milliseconds diff between "%s" and "%s"', (start, end, expected) => { + const result = calcDateMathDiff(start, end); + + expect(result).toEqual(expected); + }); + + test('returns "undefined" when start is invalid date math', () => { + const result = calcDateMathDiff('invalid', 'now-5m'); + + expect(result).toBeUndefined(); + }); + + test('returns "undefined" when end is invalid date math', () => { + const result = calcDateMathDiff('now-300s', 'invalid'); + + expect(result).toBeUndefined(); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/date_math/calc_date_math_diff.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/date_math/calc_date_math_diff.ts new file mode 100644 index 0000000000000..7e4c21cde1f57 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/date_math/calc_date_math_diff.ts @@ -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 dateMath from '@kbn/datemath'; + +/** + * Calculates difference between date math expressions in milliseconds. + */ +export function calcDateMathDiff(start: string, end: string): number | undefined { + const now = new Date(); + const startMoment = dateMath.parse(start, { forceNow: now }); + const endMoment = dateMath.parse(end, { forceNow: now }); + + if (!startMoment || !endMoment) { + return undefined; + } + + const result = endMoment.diff(startMoment, 'ms'); + + return !isNaN(result) ? result : undefined; +} diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/date_math/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/date_math/index.ts new file mode 100644 index 0000000000000..19645d895c914 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/date_math/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './calc_date_math_diff'; +export * from './normalize_date_math'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/date_math/normalize_date_math.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/date_math/normalize_date_math.test.ts new file mode 100644 index 0000000000000..72740f5063729 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/date_math/normalize_date_math.test.ts @@ -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 { normalizeDateMath } from './normalize_date_math'; + +describe('normalizeDateMath', () => { + it.each([ + ['now-60s', 'now-1m'], + ['now-60m', 'now-1h'], + ['now-24h', 'now-1d'], + ['now+60s', 'now+1m'], + ['now+60m', 'now+1h'], + ['now+24h', 'now+1d'], + ])('normalizes %s', (sourceDateMath, normalizedDateMath) => { + const result = normalizeDateMath(sourceDateMath); + + expect(result).toBe(normalizedDateMath); + }); + + it.each([['now'], ['now-invalid'], ['invalid']])('returns %s non-normalized', (dateMath) => { + const result = normalizeDateMath(dateMath); + + expect(result).toBe(dateMath); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/date_math/normalize_date_math.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/date_math/normalize_date_math.ts new file mode 100644 index 0000000000000..5e14610491bb9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/date_math/normalize_date_math.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TimeDuration } from '../time_duration/time_duration'; +import { calcDateMathDiff } from './calc_date_math_diff'; + +/** + * Normalizes date math + */ +export function normalizeDateMath(input: string): string { + try { + const ms = calcDateMathDiff('now', input); + + if (ms === undefined || (ms > -1000 && ms < 1000)) { + return input; + } + + if (ms === 0) { + return 'now'; + } + + const offset = TimeDuration.fromMilliseconds(ms); + + return offset.value < 0 ? `now${offset}` : `now+${offset}`; + } catch { + return input; + } +} diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/time_duration/time_duration.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/time_duration/time_duration.test.ts new file mode 100644 index 0000000000000..e30cae48f2f90 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/time_duration/time_duration.test.ts @@ -0,0 +1,229 @@ +/* + * 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 { TimeDuration } from './time_duration'; + +describe('TimeDuration', () => { + describe('fromMilliseconds', () => { + it.each([ + [5000, new TimeDuration(5, 's')], + [600000, new TimeDuration(10, 'm')], + [25200000, new TimeDuration(7, 'h')], + [777600000, new TimeDuration(9, 'd')], + [-3000, new TimeDuration(-3, 's')], + [-300000, new TimeDuration(-5, 'm')], + [-18000000, new TimeDuration(-5, 'h')], + [-604800000, new TimeDuration(-7, 'd')], + ])('parses "%s"', (ms, expectedTimeDuration) => { + const result = TimeDuration.fromMilliseconds(ms); + + expect(result).toEqual(expectedTimeDuration); + }); + }); + + describe('parse', () => { + it.each([ + ['5s', new TimeDuration(5, 's')], + ['10m', new TimeDuration(10, 'm')], + ['7h', new TimeDuration(7, 'h')], + ['9d', new TimeDuration(9, 'd')], + ['+5s', new TimeDuration(5, 's')], + ['+10m', new TimeDuration(10, 'm')], + ['+7h', new TimeDuration(7, 'h')], + ['+9d', new TimeDuration(9, 'd')], + ['-3s', new TimeDuration(-3, 's')], + ['-5m', new TimeDuration(-5, 'm')], + ['-5h', new TimeDuration(-5, 'h')], + ['-7d', new TimeDuration(-7, 'd')], + ['0s', new TimeDuration(0, 's')], + ['0m', new TimeDuration(0, 's')], + ['0h', new TimeDuration(0, 's')], + ['0d', new TimeDuration(0, 's')], + ['+0s', new TimeDuration(0, 's')], + ['+0m', new TimeDuration(0, 's')], + ['+0h', new TimeDuration(0, 's')], + ['+0d', new TimeDuration(0, 's')], + ['-0s', new TimeDuration(0, 's')], + ['-0m', new TimeDuration(0, 's')], + ['-0h', new TimeDuration(0, 's')], + ['-0d', new TimeDuration(0, 's')], + ])('parses "%s"', (duration, expectedTimeDuration) => { + const result = TimeDuration.parse(duration); + + expect(result).toEqual(expectedTimeDuration); + }); + + it('does NOT trim leading spaces', () => { + const result = TimeDuration.parse(' 6m'); + + expect(result).toBeUndefined(); + }); + + it('does NOT trim trailing spaces', () => { + const result = TimeDuration.parse('8h '); + + expect(result).toBeUndefined(); + }); + + it.each([[''], [' '], ['s'], ['invalid'], ['3ss'], ['m4s'], ['78']])( + 'returns "undefined" when tries to parse invalid duration "%s"', + (invalidDuration) => { + const result = TimeDuration.parse(invalidDuration); + + expect(result).toBeUndefined(); + } + ); + + it.each([['1S'], ['2M'], ['3H'], ['4D'], ['5Y'], ['7nanos'], ['8ms']])( + 'returns "undefined" when tries to parse unsupported duration units "%s"', + (invalidDuration) => { + const result = TimeDuration.parse(invalidDuration); + + expect(result).toBeUndefined(); + } + ); + }); + + describe('toMilliseconds', () => { + it.each([ + [new TimeDuration(5, 's'), 5000], + [new TimeDuration(10, 'm'), 600000], + [new TimeDuration(7, 'h'), 25200000], + [new TimeDuration(9, 'd'), 777600000], + [new TimeDuration(-3, 's'), -3000], + [new TimeDuration(-5, 'm'), -300000], + [new TimeDuration(-5, 'h'), -18000000], + [new TimeDuration(-7, 'd'), -604800000], + ])('converts %j to %d milliseconds', (timeDuration, expected) => { + const result = timeDuration.toMilliseconds(); + + expect(result).toBe(expected); + }); + + it.each([ + [new TimeDuration(0, 's')], + [new TimeDuration(0, 'm')], + [new TimeDuration(0, 'h')], + [new TimeDuration(0, 'd')], + [new TimeDuration(-0, 's')], + [new TimeDuration(-0, 'm')], + [new TimeDuration(-0, 'h')], + [new TimeDuration(-0, 'd')], + ])('converts %j to zero', (timeDuration) => { + const result = timeDuration.toMilliseconds(); + + // Handle negative zero case. Jest treats 0 !== -0. + expect(`${result}`).toBe('0'); + }); + + it.each([ + // @ts-expect-error testing invalid unit + [new TimeDuration(0, '')], + // @ts-expect-error testing invalid unit + [new TimeDuration(0, ' ')], + // @ts-expect-error testing invalid unit + [new TimeDuration(0, 'invalid')], + // @ts-expect-error testing invalid unit + [new TimeDuration(3, 'ss')], + ])('returns "undefined" when tries to convert invalid duration %j', (invalidTimeDuration) => { + const result = invalidTimeDuration.toMilliseconds(); + + expect(result).toBeUndefined(); + }); + + it.each([ + // @ts-expect-error testing invalid unit + [new TimeDuration(1, 'S')], + // @ts-expect-error testing invalid unit + [new TimeDuration(2, 'M')], + // @ts-expect-error testing invalid unit + [new TimeDuration(3, 'H')], + // @ts-expect-error testing invalid unit + [new TimeDuration(4, 'D')], + // @ts-expect-error testing invalid unit + [new TimeDuration(5, 'Y')], + // @ts-expect-error testing invalid unit + [new TimeDuration(7, 'nanos')], + // @ts-expect-error testing invalid unit + [new TimeDuration(8, 'ms')], + ])( + 'returns "undefined" when tries to convert unsupported duration units %j', + (invalidTimeDuration) => { + const result = invalidTimeDuration.toMilliseconds(); + + expect(result).toBeUndefined(); + } + ); + }); + + describe('toNormalizedTimeDuration', () => { + it.each([ + [new TimeDuration(5, 's'), new TimeDuration(5, 's')], + [new TimeDuration(65, 's'), new TimeDuration(65, 's')], + [new TimeDuration(600, 's'), new TimeDuration(10, 'm')], + [new TimeDuration(650, 's'), new TimeDuration(650, 's')], + [new TimeDuration(90, 'm'), new TimeDuration(90, 'm')], + [new TimeDuration(25200, 's'), new TimeDuration(7, 'h')], + [new TimeDuration(120, 'm'), new TimeDuration(2, 'h')], + [new TimeDuration(36, 'h'), new TimeDuration(36, 'h')], + [new TimeDuration(777600, 's'), new TimeDuration(9, 'd')], + [new TimeDuration(5184000, 's'), new TimeDuration(60, 'd')], + [new TimeDuration(1440, 'm'), new TimeDuration(1, 'd')], + [new TimeDuration(48, 'h'), new TimeDuration(2, 'd')], + [new TimeDuration(-5, 's'), new TimeDuration(-5, 's')], + [new TimeDuration(-65, 's'), new TimeDuration(-65, 's')], + [new TimeDuration(-600, 's'), new TimeDuration(-10, 'm')], + [new TimeDuration(-650, 's'), new TimeDuration(-650, 's')], + [new TimeDuration(-90, 'm'), new TimeDuration(-90, 'm')], + [new TimeDuration(-25200, 's'), new TimeDuration(-7, 'h')], + [new TimeDuration(-120, 'm'), new TimeDuration(-2, 'h')], + [new TimeDuration(-36, 'h'), new TimeDuration(-36, 'h')], + [new TimeDuration(-777600, 's'), new TimeDuration(-9, 'd')], + [new TimeDuration(-5184000, 's'), new TimeDuration(-60, 'd')], + [new TimeDuration(-1440, 'm'), new TimeDuration(-1, 'd')], + [new TimeDuration(-48, 'h'), new TimeDuration(-2, 'd')], + ])('converts %j to normalized time duration %j', (timeDuration, expected) => { + const result = timeDuration.toNormalizedTimeDuration(); + + expect(result).toEqual(expected); + }); + + it.each([ + [new TimeDuration(0, 's')], + [new TimeDuration(0, 'm')], + [new TimeDuration(0, 'h')], + [new TimeDuration(0, 'd')], + ])('converts %j to 0s', (timeDuration) => { + const result = timeDuration.toNormalizedTimeDuration(); + + expect(result).toEqual(new TimeDuration(0, 's')); + }); + + it.each([ + // @ts-expect-error testing invalid unit + [new TimeDuration(1, 'S')], + // @ts-expect-error testing invalid unit + [new TimeDuration(2, 'M')], + // @ts-expect-error testing invalid unit + [new TimeDuration(3, 'H')], + // @ts-expect-error testing invalid unit + [new TimeDuration(4, 'D')], + // @ts-expect-error testing invalid unit + [new TimeDuration(5, 'Y')], + // @ts-expect-error testing invalid unit + [new TimeDuration(7, 'nanos')], + // @ts-expect-error testing invalid unit + [new TimeDuration(8, 'ms')], + // @ts-expect-error testing invalid unit + [new TimeDuration(0, 'invalid')], + ])('returns %j unchanged', (timeDuration) => { + const result = timeDuration.toNormalizedTimeDuration(); + + expect(result).toEqual(timeDuration); + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/time_duration/time_duration.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/time_duration/time_duration.ts new file mode 100644 index 0000000000000..8fcb23cecd8e9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/time_duration/time_duration.ts @@ -0,0 +1,120 @@ +/* + * 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. + */ + +/** + * Provides a convenient way to manipulate a time duration. + * + * Time duration is stored as a string in Security Solution, e.g. + * - 5s + * - 3m + * - 7h + */ +export class TimeDuration { + /** + * Constructs a time duration from milliseconds. The output is normalized. + */ + static fromMilliseconds(ms: number): TimeDuration { + return new TimeDuration(Math.round(ms / 1000), 's').toNormalizedTimeDuration(); + } + + /* + * Parses a duration string and returns value and units. The output is normalized. + * Returns `undefined` when unable to parse. + * + * Recognizes + * - seconds (e.g. 2s) + * - minutes (e.g. 5m) + * - hours (e.g. 7h) + * - days (e.g. 9d) + */ + static parse(input: string): TimeDuration | undefined { + if (typeof input !== 'string') { + return undefined; + } + + const matchArray = input.match(TIME_DURATION_REGEX); + + if (!matchArray) { + return undefined; + } + + const value = parseInt(matchArray[1], 10); + const unit = matchArray[2] as TimeDuration['unit']; + + return new TimeDuration(value, unit).toNormalizedTimeDuration(); + } + + constructor(public value: number, public unit: TimeDurationUnits) {} + + /** + * Convert time duration to milliseconds. + * Supports + * - `s` seconds, e.g. 3s, 0s, -5s + * - `m` minutes, e.g. 10m, 0m + * - `h` hours, e.g. 7h + * - `d` days, e.g. 3d + * + * Returns `undefined` when unable to perform conversion. + */ + toMilliseconds(): number { + switch (this.unit) { + case 's': + return this.value * 1000; + case 'm': + return this.value * 1000 * 60; + case 'h': + return this.value * 1000 * 60 * 60; + case 'd': + return this.value * 1000 * 60 * 60 * 24; + } + } + + /** + * Converts time duration to the largest possible units. E.g. + * - 60s transformed to 1m + * - 3600s transformed to 1h + * - 1440m transformed to 1d + */ + toNormalizedTimeDuration(): TimeDuration { + const ms = this.toMilliseconds(); + + if (ms === undefined) { + return this; + } + + if (ms === 0) { + return new TimeDuration(0, 's'); + } + + if (ms % (3600000 * 24) === 0) { + return new TimeDuration(ms / (3600000 * 24), 'd'); + } + + if (ms % 3600000 === 0) { + return new TimeDuration(ms / 3600000, 'h'); + } + + if (ms % 60000 === 0) { + return new TimeDuration(ms / 60000, 'm'); + } + + if (ms % 1000 === 0) { + return new TimeDuration(ms / 1000, 's'); + } + + return this; + } + + toString(): string { + return `${this.value}${this.unit}`; + } +} + +const TimeDurationUnits = ['s', 'm', 'h', 'd'] as const; +type TimeDurationUnits = (typeof TimeDurationUnits)[number]; + +const TIME_DURATION_REGEX = new RegExp(`^((?:\\-|\\+)?[0-9]+)(${TimeDurationUnits.join('|')})$`); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/time_duration.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/time_duration.ts new file mode 100644 index 0000000000000..61905da7f7d8d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/time_duration.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './src/time_duration/time_duration'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/tsconfig.json b/x-pack/solutions/security/packages/kbn-securitysolution-utils/tsconfig.json index 063735a114dad..fc75ff2e16696 100644 --- a/x-pack/solutions/security/packages/kbn-securitysolution-utils/tsconfig.json +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/tsconfig.json @@ -2,21 +2,15 @@ "extends": "../../../../../tsconfig.base.json", "compilerOptions": { "outDir": "target/types", - "types": [ - "jest", - "node" - ] + "types": ["jest", "node"] }, - "include": [ - "**/*.ts" - ], + "include": ["**/*.ts"], "kbn_references": [ "@kbn/i18n", "@kbn/esql-utils", "@kbn/esql-ast", - "@kbn/esql-validation-autocomplete" + "@kbn/esql-validation-autocomplete", + "@kbn/datemath" ], - "exclude": [ - "target/**/*", - ] + "exclude": ["target/**/*"] } diff --git a/x-pack/solutions/security/plugins/cloud_defend/public/components/control_general_view_response/index.tsx b/x-pack/solutions/security/plugins/cloud_defend/public/components/control_general_view_response/index.tsx index 9511d11aa4f70..2012924544276 100644 --- a/x-pack/solutions/security/plugins/cloud_defend/public/components/control_general_view_response/index.tsx +++ b/x-pack/solutions/security/plugins/cloud_defend/public/components/control_general_view_response/index.tsx @@ -25,7 +25,6 @@ import { EuiCheckbox, EuiComboBoxOptionOption, EuiSpacer, - euiPaletteColorBlindBehindText, useEuiTheme, } from '@elastic/eui'; import { useStyles } from './styles'; @@ -61,7 +60,6 @@ export const ControlGeneralViewResponse = ({ const [isPopoverOpen, setPopoverOpen] = useState(false); const styles = useStyles(); const selectorStyles = useSelectorStyles(); - const visColorsBehindText = euiPaletteColorBlindBehindText(); const [accordionState, setAccordionState] = useState<'open' | 'closed'>( responses.length - 1 === index ? 'open' : 'closed' ); @@ -178,9 +176,9 @@ export const ControlGeneralViewResponse = ({ response.match.map((selector) => ({ label: selector as unknown as string, value: selector as unknown as string, - color: visColorsBehindText[0], + color: colors.backgroundLightSuccess, })), - [response.match, visColorsBehindText] + [response.match, colors] ); const selectedExcludes = useMemo( @@ -189,9 +187,9 @@ export const ControlGeneralViewResponse = ({ response.exclude.map((selector) => ({ label: selector as unknown as string, value: selector as unknown as string, - color: visColorsBehindText[5], + color: colors.backgroundLightWarning, })), - [response.exclude, visColorsBehindText] + [response.exclude, colors] ); const onShowExclude = useCallback(() => { diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/README.md b/x-pack/solutions/security/plugins/cloud_security_posture/README.md index aaa1b3f2377a9..c39796fa8562c 100755 --- a/x-pack/solutions/security/plugins/cloud_security_posture/README.md +++ b/x-pack/solutions/security/plugins/cloud_security_posture/README.md @@ -144,4 +144,21 @@ run serverless Cloud Security Posture e2e tests: yarn cypress:cloud_security_posture:run:serverless ``` -Unlike FTR where we have to set server and runner separately, Cypress handles everything in 1 go, so just running the above the script is enough to get it running \ No newline at end of file +Unlike FTR where we have to set server and runner separately, Cypress handles everything in 1 go, so just running the above the script is enough to get it running + +### Troubleshooting + +If you encounter an error related to running machine learning code, you should add the following string `'xpack.ml.enabled=false'` under the `esTestCluster` property in the `x-pack/test/functional/config.base.js` file. + +Example: +```javascript +module.exports = { + esTestCluster: { + // ...existing configuration... + serverArgs: [ + // ...existing arguments... + 'xpack.ml.enabled=false', // Add this line to disable ML + ], + }, + // ...other configurations... +}; \ No newline at end of file diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/common/types_old.ts b/x-pack/solutions/security/plugins/cloud_security_posture/common/types_old.ts index be5366b89bc24..12859e5512045 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/common/types_old.ts +++ b/x-pack/solutions/security/plugins/cloud_security_posture/common/types_old.ts @@ -6,7 +6,10 @@ */ import { type TypeOf } from '@kbn/config-schema'; import type { CspBenchmarkRuleMetadata } from '@kbn/cloud-security-posture-common/schema/rules/latest'; -import type { CspFinding } from '@kbn/cloud-security-posture-common'; +import type { + CspFinding, + MisconfigurationEvaluationStatus, +} from '@kbn/cloud-security-posture-common'; import { SUPPORTED_CLOUDBEAT_INPUTS, SUPPORTED_POLICY_TEMPLATES } from './constants'; import { getComplianceDashboardSchema } from './schemas/stats'; @@ -36,7 +39,7 @@ export type AzureCredentialsType = | 'service_principal_with_client_username_and_password' | 'managed_identity'; -export type Evaluation = 'passed' | 'failed' | 'NA'; +export type Evaluation = MisconfigurationEvaluationStatus; export type PostureTypes = 'cspm' | 'kspm' | 'vuln_mgmt' | 'all'; /** number between 1-100 */ diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/assets/icons/nvd_logo_svg.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/assets/icons/nvd_logo_svg.tsx index b8dc583356cec..936d87ad0f236 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/assets/icons/nvd_logo_svg.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/assets/icons/nvd_logo_svg.tsx @@ -5,24 +5,29 @@ * 2.0. */ -import { euiThemeVars } from '@kbn/ui-theme'; +import { useEuiTheme } from '@elastic/eui'; import React from 'react'; -export const NvdLogo = () => ( - - - - -); +// TODO: Borealis migration - replace fullShade with a proper color token, see https://github.com/elastic/kibana/issues/199715#issuecomment-2535949093 +export const NvdLogo = () => { + const { euiTheme } = useEuiTheme(); + + return ( + + + + + ); +}; diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/common/constants.ts b/x-pack/solutions/security/plugins/cloud_security_posture/public/common/constants.ts index 2039506c8cdde..52a4f5a8a2b3c 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/common/constants.ts +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/common/constants.ts @@ -176,7 +176,9 @@ export const FINDINGS_GROUPING_OPTIONS = { RULE_NAME: 'rule.name', RULE_SECTION: 'rule.section', CLOUD_ACCOUNT_NAME: 'cloud.account.name', + CLOUD_ACCOUNT_ID: 'cloud.account.id', ORCHESTRATOR_CLUSTER_NAME: 'orchestrator.cluster.name', + ORCHESTRATOR_CLUSTER_ID: 'orchestrator.cluster.id', }; export const VULNERABILITY_FIELDS = { @@ -224,6 +226,6 @@ the fields from the runtime mappings if they are removed from the Data Table. */ export const CDR_VULNERABILITY_GROUPING_RUNTIME_MAPPING_FIELDS: Record = {}; export const CDR_MISCONFIGURATION_GROUPING_RUNTIME_MAPPING_FIELDS: Record = { - [FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_NAME]: ['orchestrator.cluster.name'], - [FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_NAME]: ['cloud.account.name'], + [FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_ID]: ['orchestrator.cluster.id'], + [FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_ID]: ['cloud.account.id'], }; diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.test.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.test.tsx index 9f5f2ec85d021..470a04e402489 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.test.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.test.tsx @@ -47,7 +47,7 @@ describe('AccountsEvaluatedWidget', () => { 'cloud.provider': 'aws', 'rule.benchmark.posture_type': 'cspm', }, - ['cloud.account.name'] + ['cloud.account.id'] ); }); @@ -64,7 +64,7 @@ describe('AccountsEvaluatedWidget', () => { { 'rule.benchmark.id': 'cis_k8s', }, - ['orchestrator.cluster.name'] + ['orchestrator.cluster.id'] ); }); }); diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.tsx index 5ae8a47a93e71..80716efd98690 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.tsx @@ -64,13 +64,13 @@ export const AccountsEvaluatedWidget = ({ const navToFindingsByCloudProvider = (provider: string) => { navToFindings( { 'cloud.provider': provider, 'rule.benchmark.posture_type': CSPM_POLICY_TEMPLATE }, - [FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_NAME] + [FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_ID] ); }; const navToFindingsByCisBenchmark = (cisBenchmark: string) => { navToFindings({ 'rule.benchmark.id': cisBenchmark }, [ - FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_NAME, + FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_ID, ]); }; diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/components/compliance_score_bar.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/components/compliance_score_bar.tsx index 3829542829909..3015f2bfd100b 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/components/compliance_score_bar.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/components/compliance_score_bar.tsx @@ -9,7 +9,8 @@ import { EuiFlexGroup, EuiFlexItem, EuiText, EuiToolTip, useEuiTheme } from '@el import { css, SerializedStyles } from '@emotion/react'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { statusColors } from '@kbn/cloud-security-posture'; +import { MISCONFIGURATION_STATUS } from '@kbn/cloud-security-posture-common'; +import { getMisconfigurationStatusColor } from '@kbn/cloud-security-posture'; import { calculatePostureScore } from '../../common/utils/helpers'; import { CSP_FINDINGS_COMPLIANCE_SCORE, @@ -68,7 +69,7 @@ export const ComplianceScoreBar = ({ @@ -77,7 +78,7 @@ export const ComplianceScoreBar = ({ @@ -86,7 +87,7 @@ export const ComplianceScoreBar = ({ diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/components/vulnerability_severity_map.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/components/vulnerability_severity_map.tsx index 4773f5378fb3e..ad6051c2edada 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/components/vulnerability_severity_map.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/components/vulnerability_severity_map.tsx @@ -15,10 +15,10 @@ import { EuiText, } from '@elastic/eui'; import { PaletteColorStop } from '@elastic/eui/src/components/color_picker/color_palette_picker'; -import type { VulnSeverity } from '@kbn/cloud-security-posture-common'; import { i18n } from '@kbn/i18n'; -import { getSeverityStatusColor } from '@kbn/cloud-security-posture'; +import type { VulnSeverity } from '@kbn/cloud-security-posture-common'; import { SeverityStatusBadge } from '@kbn/cloud-security-posture'; +import { useGetSeverityStatusColor } from '@kbn/cloud-security-posture/src/hooks/use_get_severity_status_color'; interface Props { total: number; @@ -52,6 +52,7 @@ const formatPercentage = (percentage: number) => { export const VulnerabilitySeverityMap = ({ severityMap, total }: Props) => { const { euiTheme } = useEuiTheme(); + const { getSeverityStatusColor } = useGetSeverityStatusColor(); const severityMapPallet: PaletteColorStop[] = []; const severityMapTooltip: SeverityMapTooltip[] = []; diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx index 27b32345d85ca..5c10703bc5adc 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx @@ -145,14 +145,12 @@ const getBenchmarkTableColumns = ( 'data-test-subj': TEST_SUBJ.BENCHMARKS_TABLE_COLUMNS.APPLICABLE_TO, render: (benchmarkId: BenchmarksCisId) => { return ( - <> - - - - - {getBenchmarkApplicableTo(benchmarkId)} - - + + + + + {getBenchmarkApplicableTo(benchmarkId)} + ); }, }, @@ -189,8 +187,8 @@ const getBenchmarkTableColumns = ( const isKspmBenchmark = ['cis_k8s', 'cis_eks'].includes(benchmark.id); const groupByField = isKspmBenchmark - ? FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_NAME - : FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_NAME; + ? FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_ID + : FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_ID; return ( void; stats: { totalPassed: number; totalFailed: number }; -}) => ( - <> - onEvalCounterClick(RULE_PASSED)} - tooltipContent={i18n.translate( - 'xpack.csp.complianceScoreChart.counterLink.passedFindingsTooltip', - { defaultMessage: 'Passed findings' } - )} - /> -  -  - onEvalCounterClick(RULE_FAILED)} - tooltipContent={i18n.translate( - 'xpack.csp.complianceScoreChart.counterButtonLink.failedFindingsTooltip', - { defaultMessage: 'Failed findings' } - )} - /> - -); +}) => { + return ( + <> + onEvalCounterClick(RULE_PASSED)} + tooltipContent={i18n.translate( + 'xpack.csp.complianceScoreChart.counterLink.passedFindingsTooltip', + { defaultMessage: 'Passed findings' } + )} + /> +  -  + onEvalCounterClick(RULE_FAILED)} + tooltipContent={i18n.translate( + 'xpack.csp.complianceScoreChart.counterButtonLink.failedFindingsTooltip', + { defaultMessage: 'Failed findings' } + )} + /> + + ); +}; const PercentageLabels = ({ onEvalCounterClick, @@ -144,13 +147,14 @@ const PercentageLabels = ({ }) => { const { euiTheme } = useEuiTheme(); const borderLeftStyles = { borderLeft: euiTheme.border.thin, paddingLeft: euiTheme.size.m }; + return ( onEvalCounterClick(RULE_PASSED)} /> @@ -159,7 +163,7 @@ const PercentageLabels = ({ onEvalCounterClick(RULE_FAILED)} /> diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmark_details_box.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmark_details_box.tsx index aef4086ea027f..869b1473b443b 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmark_details_box.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmark_details_box.tsx @@ -34,11 +34,11 @@ export const BenchmarkDetailsBox = ({ benchmark }: { benchmark: BenchmarkData }) const navToFindings = useNavigateFindings(); const handleClickCloudProvider = () => - navToFindings(getBenchmarkIdQuery(benchmark), [FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_NAME]); + navToFindings(getBenchmarkIdQuery(benchmark), [FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_ID]); const handleClickCluster = () => navToFindings(getBenchmarkIdQuery(benchmark), [ - FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_NAME, + FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_ID, ]); const getBenchmarkInfo = (benchmarkId: string, cloudAssetCount: number): BenchmarkInfo => { diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_flyout.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_flyout.tsx index 462652b4869de..8ab9e9465dada 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_flyout.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_flyout.tsx @@ -34,7 +34,6 @@ import { i18n } from '@kbn/i18n'; import type { HttpSetup } from '@kbn/core/public'; import { generatePath } from 'react-router-dom'; import { css } from '@emotion/react'; -import { euiThemeVars } from '@kbn/ui-theme'; import { CspEvaluationBadge } from '@kbn/cloud-security-posture'; import type { CspFinding } from '@kbn/cloud-security-posture-common'; import { CspVulnerabilityFinding } from '@kbn/cloud-security-posture-common/schema/vulnerabilities/csp_vulnerability_finding'; @@ -240,6 +239,7 @@ export const FindingsRuleFlyout = ({ findingsCount, onPaginate, }: FindingFlyoutProps) => { + const { euiTheme } = useEuiTheme(); const [tab, setTab] = useState(tabs[0]); const createMisconfigurationRuleFn = async (http: HttpSetup) => @@ -263,7 +263,7 @@ export const FindingsRuleFlyout = ({
{!isNativeCspFinding(finding) && ['overview', 'rule'].includes(tab.id) && ( -
+
)} diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/latest_findings/constants.ts b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/latest_findings/constants.ts index 4ccf6caf68ea6..8612c754ac35c 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/latest_findings/constants.ts +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/latest_findings/constants.ts @@ -35,12 +35,12 @@ export const MISCONFIGURATIONS_GROUPS_UNIT = ( values: { groupCount }, defaultMessage: `{groupCount} {groupCount, plural, =1 {rule} other {rules}}`, }); - case FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_NAME: + case FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_ID: return i18n.translate('xpack.csp.findings.groupUnit.cloudAccount', { values: { groupCount }, defaultMessage: `{groupCount} {groupCount, plural, =1 {cloud account} other {cloud accounts}}`, }); - case FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_NAME: + case FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_ID: return i18n.translate('xpack.csp.findings.groupUnit.kubernetes', { values: { groupCount }, defaultMessage: `{groupCount} {groupCount, plural, =1 {kubernetes cluster} other {kubernetes clusters}}`, @@ -67,10 +67,9 @@ export const NULL_GROUPING_MESSAGES = { CLOUD_ACCOUNT_NAME: i18n.translate('xpack.csp.findings.grouping.cloudAccount.nullGroupTitle', { defaultMessage: 'No cloud account', }), - ORCHESTRATOR_CLUSTER_NAME: i18n.translate( - 'xpack.csp.findings.grouping.kubernetes.nullGroupTitle', - { defaultMessage: 'No Kubernetes cluster' } - ), + ORCHESTRATOR_CLUSTER_ID: i18n.translate('xpack.csp.findings.grouping.kubernetes.nullGroupTitle', { + defaultMessage: 'No Kubernetes cluster', + }), DEFAULT: i18n.translate('xpack.csp.findings.grouping.default.nullGroupTitle', { defaultMessage: 'No grouping', }), @@ -91,15 +90,15 @@ export const defaultGroupingOptions: GroupOption[] = [ }, { label: i18n.translate('xpack.csp.findings.latestFindings.groupByCloudAccount', { - defaultMessage: 'Cloud account', + defaultMessage: 'Cloud account ID', }), - key: FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_NAME, + key: FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_ID, }, { label: i18n.translate('xpack.csp.findings.latestFindings.groupByKubernetesCluster', { - defaultMessage: 'Kubernetes cluster', + defaultMessage: 'Kubernetes cluster ID', }), - key: FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_NAME, + key: FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_ID, }, ]; diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/latest_findings/latest_findings_group_renderer.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/latest_findings/latest_findings_group_renderer.tsx index 743b0bc95cb43..2fbc09d3f2494 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/latest_findings/latest_findings_group_renderer.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/latest_findings/latest_findings_group_renderer.tsx @@ -14,7 +14,7 @@ import { useEuiTheme, } from '@elastic/eui'; import { css } from '@emotion/react'; -import { GroupPanelRenderer, GroupStatsItem, RawBucket } from '@kbn/grouping/src'; +import { GenericBuckets, GroupPanelRenderer, GroupStatsItem, RawBucket } from '@kbn/grouping/src'; import React from 'react'; import { i18n } from '@kbn/i18n'; import { getAbbreviatedNumber } from '@kbn/cloud-security-posture-common'; @@ -45,13 +45,15 @@ export const groupPanelRenderer: GroupPanelRenderer ); - const getGroupPanelTitle = () => { - const resourceId = bucket.resourceName?.buckets?.[0]?.key; + const getGroupPanelTitle = (aggregationField?: keyof FindingsGroupingAggregation) => { + const aggregationFieldValue = aggregationField + ? (bucket[aggregationField] as { buckets?: GenericBuckets[] })?.buckets?.[0]?.key + : null; - if (resourceId) { + if (aggregationFieldValue) { return ( <> - {resourceId} - {bucket.key_as_string} + {aggregationFieldValue} - {bucket.key_as_string} ); } @@ -80,7 +82,7 @@ export const groupPanelRenderer: GroupPanelRenderer `} title={bucket.resourceName?.buckets?.[0]?.key as string} > - {getGroupPanelTitle()} + {getGroupPanelTitle('resourceName')} @@ -101,9 +103,7 @@ export const groupPanelRenderer: GroupPanelRenderer - - {bucket.key_as_string} - + {getGroupPanelTitle()} @@ -115,7 +115,7 @@ export const groupPanelRenderer: GroupPanelRenderer ); - case FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_NAME: + case FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_ID: return nullGroupMessage ? ( renderNullGroup(NULL_GROUPING_MESSAGES.CLOUD_ACCOUNT_NAME) ) : ( @@ -131,9 +131,7 @@ export const groupPanelRenderer: GroupPanelRenderer - - {bucket.key_as_string} - + {getGroupPanelTitle('accountName')} @@ -144,9 +142,9 @@ export const groupPanelRenderer: GroupPanelRenderer ); - case FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_NAME: + case FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_ID: return nullGroupMessage ? ( - renderNullGroup(NULL_GROUPING_MESSAGES.ORCHESTRATOR_CLUSTER_NAME) + renderNullGroup(NULL_GROUPING_MESSAGES.ORCHESTRATOR_CLUSTER_ID) ) : ( {benchmarkId && ( @@ -160,9 +158,7 @@ export const groupPanelRenderer: GroupPanelRenderer - - {bucket.key_as_string} - + {getGroupPanelTitle('clusterName')} @@ -181,9 +177,7 @@ export const groupPanelRenderer: GroupPanelRenderer - - {bucket.key_as_string} - + {getGroupPanelTitle()} diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_grouped_findings.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_grouped_findings.tsx index 842e21c58a971..438e6b0778e2b 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_grouped_findings.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_grouped_findings.tsx @@ -61,6 +61,12 @@ export interface FindingsGroupingAggregation { benchmarkId?: { buckets?: GenericBuckets[]; }; + accountName?: { + buckets?: GenericBuckets[]; + }; + clusterName?: { + buckets?: GenericBuckets[]; + }; isLoading?: boolean; } diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx index 87e0969a5966c..f591115792e08 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx @@ -98,17 +98,19 @@ const getAggregationsByGroupField = (field: string): NamedAggregation[] => { getTermAggregation('benchmarkName', 'rule.benchmark.name'), getTermAggregation('benchmarkVersion', 'rule.benchmark.version'), ]; - case FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_NAME: + case FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_ID: return [ ...aggMetrics, getTermAggregation('benchmarkName', 'rule.benchmark.name'), getTermAggregation('benchmarkId', 'rule.benchmark.id'), + getTermAggregation('accountName', 'cloud.account.name'), ]; - case FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_NAME: + case FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_ID: return [ ...aggMetrics, getTermAggregation('benchmarkName', 'rule.benchmark.name'), getTermAggregation('benchmarkId', 'rule.benchmark.id'), + getTermAggregation('clusterName', 'orchestrator.cluster.name'), ]; } return aggMetrics; diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/layout/findings_distribution_bar.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/layout/findings_distribution_bar.tsx index 3fe31785f81df..055e4b054f508 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/layout/findings_distribution_bar.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/configurations/layout/findings_distribution_bar.tsx @@ -8,8 +8,8 @@ import React from 'react'; import { css } from '@emotion/react'; import { EuiHealth, EuiBadge, EuiSpacer, EuiFlexGroup, useEuiTheme } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { statusColors } from '@kbn/cloud-security-posture'; -import { getAbbreviatedNumber } from '@kbn/cloud-security-posture-common'; +import { getMisconfigurationStatusColor } from '@kbn/cloud-security-posture'; +import { getAbbreviatedNumber, MISCONFIGURATION_STATUS } from '@kbn/cloud-security-posture-common'; import { RULE_FAILED, RULE_PASSED } from '../../../../common/constants'; import type { Evaluation } from '../../../../common/types_old'; @@ -44,9 +44,13 @@ const Counters = ({ passed, failed }: Pick) => { gap: ${euiTheme.size.m}; `} > - {I18N_PASSED_FINDINGS} + + {I18N_PASSED_FINDINGS} + {getAbbreviatedNumber(passed)} - {I18N_FAILED_FINDINGS} + + {I18N_FAILED_FINDINGS} + {getAbbreviatedNumber(failed)} ); @@ -69,7 +73,7 @@ const DistributionBar: React.FC> = ({ > { distributionOnClick(RULE_PASSED); }} @@ -78,7 +82,7 @@ const DistributionBar: React.FC> = ({ /> { distributionOnClick(RULE_FAILED); }} diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx index ff427e7809454..e65bee10243d6 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx @@ -47,7 +47,7 @@ const getTestComponent = ...coreStart.application, capabilities: { ...coreStart.application.capabilities, - siem: { crud: true }, + siemV2: { crud: true }, }, }, }; diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx index 4718dbae911ae..a5c5a534db189 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx @@ -47,7 +47,7 @@ const getWrapper = ...coreStart.application, capabilities: { ...coreStart.application.capabilities, - siem: { crud: canUpdate }, + siemV2: { crud: canUpdate }, }, }, }; diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/rules/rules_counters.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/rules/rules_counters.tsx index 15dca8e9b76ff..e2d5e78de0954 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/rules/rules_counters.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/rules/rules_counters.tsx @@ -18,7 +18,8 @@ import { i18n } from '@kbn/i18n'; import { useParams } from 'react-router-dom'; import { Chart, Partition, PartitionLayout, Settings } from '@elastic/charts'; import { FormattedMessage } from '@kbn/i18n-react'; -import { statusColors } from '@kbn/cloud-security-posture'; +import { MISCONFIGURATION_STATUS } from '@kbn/cloud-security-posture-common'; +import { getMisconfigurationStatusColor } from '@kbn/cloud-security-posture'; import { useNavigateFindings } from '@kbn/cloud-security-posture/src/hooks/use_navigate_findings'; import { useBenchmarkDynamicValues } from '../../common/hooks/use_benchmark_dynamic_values'; import { getPostureScorePercentage } from '../compliance_dashboard/compliance_charts/compliance_score_chart'; @@ -74,8 +75,8 @@ const EvaluationPieChart = ({ failed, passed }: { failed: number; passed: number shape: { fillColor: (label) => label.toLowerCase() === RULE_PASSED.toLowerCase() - ? statusColors.passed - : statusColors.failed, + ? getMisconfigurationStatusColor(MISCONFIGURATION_STATUS.PASSED) + : getMisconfigurationStatusColor(MISCONFIGURATION_STATUS.FAILED), }, }, ]} @@ -232,7 +233,10 @@ export const RulesCounters = ({ defaultMessage: 'Failed Findings', }), title: benchmarkRulesStats.score.totalFailed, - titleColor: benchmarkRulesStats.score.totalFailed > 0 ? statusColors.failed : undefined, + titleColor: + benchmarkRulesStats.score.totalFailed > 0 + ? getMisconfigurationStatusColor(MISCONFIGURATION_STATUS.FAILED) + : undefined, button: ( { + const { euiTheme } = useEuiTheme(); const [selectedTabId, setSelectedTabId] = useState(overviewTabId); const vulnerability = vulnerabilityRecord?.vulnerability; @@ -176,7 +177,7 @@ export const VulnerabilityFindingFlyout = ({ @@ -186,14 +187,14 @@ export const VulnerabilityFindingFlyout = ({ @@ -210,7 +211,7 @@ export const VulnerabilityFindingFlyout = ({
{!isNativeCspFinding(vulnerabilityRecord) && selectedTabId === overviewTabId && ( -
+
)} diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_overview_tab.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_overview_tab.tsx index 9592ceec167b9..ffe647b4b7640 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_overview_tab.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_overview_tab.tsx @@ -12,12 +12,12 @@ import { EuiIcon, EuiLink, EuiText, + useEuiTheme, } from '@elastic/eui'; import { css } from '@emotion/react'; import { FormattedMessage } from '@kbn/i18n-react'; import moment from 'moment'; import React from 'react'; -import { euiThemeVars } from '@kbn/ui-theme'; import { i18n } from '@kbn/i18n'; import { VectorScoreBase, @@ -61,6 +61,7 @@ interface VulnerabilityTabProps { const EMPTY_VALUE = '-'; const CVSScore = ({ vectorBaseScore, vendor }: CVSScoreProps) => { + const { euiTheme } = useEuiTheme(); const vendorName = cvssVendors[vendor]; const vectorScores = getVectorScoreList(vectorBaseScore); @@ -69,9 +70,9 @@ const CVSScore = ({ vectorBaseScore, vendor }: CVSScoreProps) => { { + const { euiTheme } = useEuiTheme(); const { score, vector, version } = vectorScore; return ( <> {vector}{' '} @@ -145,10 +147,11 @@ const VectorScore = ({ }; const VulnerabilityOverviewTiles = ({ vulnerabilityRecord }: VulnerabilityTabProps) => { + const { euiTheme } = useEuiTheme(); const { vulnerability } = vulnerabilityRecord; const tileStyle = css` - padding: ${euiThemeVars.euiFontSizeM}; - background: ${euiThemeVars.euiColorLightestShade}; + padding: ${euiTheme.size.m}; + background: ${euiTheme.colors.backgroundLightText}; border-radius: 6px; height: 74px; `; @@ -222,6 +225,7 @@ const VulnerabilityOverviewTiles = ({ vulnerabilityRecord }: VulnerabilityTabPro }; export const VulnerabilityOverviewTab = ({ vulnerabilityRecord }: VulnerabilityTabProps) => { + const { euiTheme } = useEuiTheme(); const { vulnerability } = vulnerabilityRecord; uiMetricService.trackUiMetric(METRIC_TYPE.COUNT, VULNERABILITIES_FLYOUT_VISITS); @@ -255,9 +259,9 @@ export const VulnerabilityOverviewTab = ({ vulnerabilityRecord }: VulnerabilityT `; const flyoutSubheadingStyle = css` - font-size: ${euiThemeVars.euiFontSizeM}; + font-size: ${euiTheme.size.m}; line-height: 24px; - margin-bottom: ${euiThemeVars.euiSizeS}; + margin-bottom: ${euiTheme.size.s}; font-weight: 600; `; @@ -329,7 +333,7 @@ export const VulnerabilityOverviewTab = ({ vulnerabilityRecord }: VulnerabilityT direction="column" gutterSize="l" css={css` - margin-top: ${euiThemeVars.euiSizeS}; + margin-top: ${euiTheme.size.s}; `} > {!!cvssScores?.length ? cvssScores : EMPTY_VALUE} diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_statistics.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_statistics.tsx index de1f7ec3ba37a..f1df3c3d5f95f 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_statistics.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_statistics.tsx @@ -8,13 +8,14 @@ import React, { useMemo } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiHealth } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useNavigateNativeVulnerabilities } from '@kbn/cloud-security-posture/src/hooks/use_navigate_findings'; +import { useGetSeverityStatusColor } from '@kbn/cloud-security-posture/src/hooks/use_get_severity_status_color'; import { VULNERABILITIES_SEVERITY } from '@kbn/cloud-security-posture-common'; -import { getSeverityStatusColor } from '@kbn/cloud-security-posture'; import { VulnCounterCard, type VulnCounterCardProps } from '../../components/vuln_counter_card'; import { useVulnerabilityDashboardApi } from '../../common/api/use_vulnerability_dashboard_api'; import { CompactFormattedNumber } from '../../components/compact_formatted_number'; export const VulnerabilityStatistics = () => { + const { getSeverityStatusColor } = useGetSeverityStatusColor(); const navToVulnerabilities = useNavigateNativeVulnerabilities(); const getVulnerabilityDashboard = useVulnerabilityDashboardApi(); @@ -103,7 +104,7 @@ export const VulnerabilityStatistics = () => { }), }, ], - [getVulnerabilityDashboard.data, navToVulnerabilities] + [getVulnerabilityDashboard.data, navToVulnerabilities, getSeverityStatusColor] ); return ( diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_trend_graph.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_trend_graph.tsx index 599928eea88b8..47097d261c0cb 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_trend_graph.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_trend_graph.tsx @@ -20,9 +20,9 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { useNavigateNativeVulnerabilities } from '@kbn/cloud-security-posture/src/hooks/use_navigate_findings'; +import { useGetSeverityStatusColor } from '@kbn/cloud-security-posture/src/hooks/use_get_severity_status_color'; import type { VulnSeverity } from '@kbn/cloud-security-posture-common'; import { VULNERABILITIES_SEVERITY } from '@kbn/cloud-security-posture-common'; -import { getSeverityStatusColor } from '@kbn/cloud-security-posture'; import { truthy } from '../../../common/utils/helpers'; import { VulnStatsTrend } from '../../../common/types_old'; import { useVulnerabilityDashboardApi } from '../../common/api/use_vulnerability_dashboard_api'; @@ -156,6 +156,7 @@ export const VulnerabilityTrendGraph = () => { const { services: { charts }, } = useKibana(); + const { getSeverityStatusColor } = useGetSeverityStatusColor(); const getVulnerabilityDashboard = useVulnerabilityDashboardApi(); const vulnTrends = getVulnerabilityDashboard.data?.vulnTrends || []; const [selectedAccount, setSelectedAccount] = useState(DEFAULT_ACCOUNT); @@ -189,7 +190,7 @@ export const VulnerabilityTrendGraph = () => { color: getSeverityStatusColor(VULNERABILITIES_SEVERITY.CRITICAL), }, ], - [] + [getSeverityStatusColor] ); return ( diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/tsconfig.json b/x-pack/solutions/security/plugins/cloud_security_posture/tsconfig.json index e723ae3bc5d9f..c9fe35a099908 100755 --- a/x-pack/solutions/security/plugins/cloud_security_posture/tsconfig.json +++ b/x-pack/solutions/security/plugins/cloud_security_posture/tsconfig.json @@ -30,7 +30,6 @@ "@kbn/charts-plugin", "@kbn/discover-plugin", "@kbn/i18n", - "@kbn/ui-theme", "@kbn/i18n-react", "@kbn/es-query", "@kbn/data-views-plugin", diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/ai_assistant_data_clients/index.test.ts b/x-pack/solutions/security/plugins/elastic_assistant/server/ai_assistant_data_clients/index.test.ts index 007e25e9af467..23e6e5e681d53 100644 --- a/x-pack/solutions/security/plugins/elastic_assistant/server/ai_assistant_data_clients/index.test.ts +++ b/x-pack/solutions/security/plugins/elastic_assistant/server/ai_assistant_data_clients/index.test.ts @@ -80,12 +80,10 @@ describe('AIAssistantDataClient', () => { }); const reader = await assistantConversationsDataClient.getReader(); const query = { query: { bool: { filter: { range: { '@timestamp': { gte: 0 } } } } } }; - await reader.search({ - body: query, - }); + await reader.search(query); expect(clusterClient.search).toHaveBeenCalledWith({ - body: query, + ...query, ignore_unavailable: true, index: '.kibana-elastic-ai-assistant-conversations-default', seq_no_primary_term: true, @@ -102,11 +100,9 @@ describe('AIAssistantDataClient', () => { const reader = await assistantConversationsDataClient.getReader(); const query = { query: { bool: { filter: { range: { '@timestamp': { gte: 0 } } } } } }; - await expect( - reader.search({ - body: query, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot(`"something went wrong!"`); + await expect(reader.search(query)).rejects.toThrowErrorMatchingInlineSnapshot( + `"something went wrong!"` + ); expect(logger.error).toHaveBeenCalledWith( `Error performing search in AIAssistantDataClient - something went wrong!` diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/ai_assistant_data_clients/knowledge_base/index.ts b/x-pack/solutions/security/plugins/elastic_assistant/server/ai_assistant_data_clients/knowledge_base/index.ts index 89a2b834bf906..854c83ac4f5a9 100644 --- a/x-pack/solutions/security/plugins/elastic_assistant/server/ai_assistant_data_clients/knowledge_base/index.ts +++ b/x-pack/solutions/security/plugins/elastic_assistant/server/ai_assistant_data_clients/knowledge_base/index.ts @@ -9,6 +9,7 @@ import { MlTrainedModelDeploymentNodesStats, MlTrainedModelStats, SearchTotalHits, + QueryDslQueryContainer, } from '@elastic/elasticsearch/lib/api/types'; import type { MlPluginSetup } from '@kbn/ml-plugin/server'; import type { KibanaRequest } from '@kbn/core-http-server'; @@ -23,7 +24,6 @@ import { Metadata, } from '@kbn/elastic-assistant-common'; import pRetry from 'p-retry'; -import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { StructuredTool } from '@langchain/core/tools'; import { AnalyticsServiceSetup, AuditLogger, ElasticsearchClient } from '@kbn/core/server'; import { IndexPatternsFetcher } from '@kbn/data-views-plugin/server'; diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/ai_assistant_service/index.test.ts b/x-pack/solutions/security/plugins/elastic_assistant/server/ai_assistant_service/index.test.ts index 32a1a30fec255..b94a46e81a937 100644 --- a/x-pack/solutions/security/plugins/elastic_assistant/server/ai_assistant_service/index.test.ts +++ b/x-pack/solutions/security/plugins/elastic_assistant/server/ai_assistant_service/index.test.ts @@ -6,7 +6,7 @@ */ import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; -import { IndicesGetDataStreamResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { IndicesGetDataStreamResponse } from '@elastic/elasticsearch/lib/api/types'; import { errors as EsErrors } from '@elastic/elasticsearch'; import { ReplaySubject, Subject } from 'rxjs'; import { taskManagerMock } from '@kbn/task-manager-plugin/server/mocks'; diff --git a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/alerts/8.13.0/index.ts b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/alerts/8.13.0/index.ts index e7066058ab8db..ea4f964fd8163 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/alerts/8.13.0/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/alerts/8.13.0/index.ts @@ -40,7 +40,7 @@ export interface BaseFields8130 extends BaseFields8120 { [ALERT_HOST_CRITICALITY]: string | undefined; [ALERT_USER_CRITICALITY]: string | undefined; /** - * Risk scores fields was added aroung 8.5.0, but the fields were not added to the alert schema + * Risk scores fields was added around 8.5.0, but the fields were not added to the alert schema */ [ALERT_HOST_RISK_SCORE_CALCULATED_LEVEL]: string | undefined; [ALERT_HOST_RISK_SCORE_CALCULATED_SCORE_NORM]: number | undefined; diff --git a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/alerts/8.18.0/index.ts b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/alerts/8.18.0/index.ts new file mode 100644 index 0000000000000..a98e99289da15 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/alerts/8.18.0/index.ts @@ -0,0 +1,62 @@ +/* + * 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 { AlertWithCommonFields800 } from '@kbn/rule-registry-plugin/common/schemas/8.0.0'; +import type { + Ancestor8160, + BaseFields8160, + EqlBuildingBlockFields8160, + EqlShellFields8160, + NewTermsFields8160, +} from '../8.16.0'; +import type { + ALERT_SERVICE_CRITICALITY, + ALERT_SERVICE_RISK_SCORE_CALCULATED_LEVEL, + ALERT_SERVICE_RISK_SCORE_CALCULATED_SCORE_NORM, +} from '../../../../../field_maps/field_names'; + +/* DO NOT MODIFY THIS SCHEMA TO ADD NEW FIELDS. These types represent the alerts that shipped in 8.18.0. +Any changes to these types should be bug fixes so the types more accurately represent the alerts from 8.18.0. +If you are adding new fields for a new release of Kibana, create a new sibling folder to this one +for the version to be released and add the field(s) to the schema in that folder. +Then, update `../index.ts` to import from the new folder that has the latest schemas, add the +new schemas to the union of all alert schemas, and re-export the new schemas as the `*Latest` schemas. +*/ + +export type { Ancestor8160 as Ancestor8180 }; + +export interface BaseFields8180 extends BaseFields8160 { + [ALERT_SERVICE_CRITICALITY]: string | undefined; + [ALERT_SERVICE_RISK_SCORE_CALCULATED_LEVEL]: string | undefined; + [ALERT_SERVICE_RISK_SCORE_CALCULATED_SCORE_NORM]: number | undefined; +} + +export interface WrappedFields8180 { + _id: string; + _index: string; + _source: T; +} + +export type GenericAlert8180 = AlertWithCommonFields800; + +export type EqlShellFields8180 = EqlShellFields8160 & BaseFields8180; + +export type EqlBuildingBlockFields8180 = EqlBuildingBlockFields8160 & BaseFields8180; + +export type NewTermsFields8180 = NewTermsFields8160 & BaseFields8180; + +export type NewTermsAlert8180 = NewTermsFields8160 & BaseFields8180; + +export type EqlBuildingBlockAlert8180 = AlertWithCommonFields800; + +export type EqlShellAlert8180 = AlertWithCommonFields800; + +export type DetectionAlert8180 = + | GenericAlert8180 + | EqlShellAlert8180 + | EqlBuildingBlockAlert8180 + | NewTermsAlert8180; diff --git a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/alerts/index.ts b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/alerts/index.ts index 816c9a4c81897..6758b88bbb6ae 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/alerts/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/alerts/index.ts @@ -15,15 +15,16 @@ import type { DetectionAlert890 } from './8.9.0'; import type { DetectionAlert8120 } from './8.12.0'; import type { DetectionAlert8130 } from './8.13.0'; +import type { DetectionAlert8160 } from './8.16.0'; import type { - Ancestor8160, - BaseFields8160, - DetectionAlert8160, - EqlBuildingBlockFields8160, - EqlShellFields8160, - NewTermsFields8160, - WrappedFields8160, -} from './8.16.0'; + Ancestor8180, + BaseFields8180, + DetectionAlert8180, + EqlBuildingBlockFields8180, + EqlShellFields8180, + NewTermsFields8180, + WrappedFields8180, +} from './8.18.0'; // When new Alert schemas are created for new Kibana versions, add the DetectionAlert type from the new version // here, e.g. `export type DetectionAlert = DetectionAlert800 | DetectionAlert820` if a new schema is created in 8.2.0 @@ -36,14 +37,15 @@ export type DetectionAlert = | DetectionAlert890 | DetectionAlert8120 | DetectionAlert8130 - | DetectionAlert8160; + | DetectionAlert8160 + | DetectionAlert8180; export type { - Ancestor8160 as AncestorLatest, - BaseFields8160 as BaseFieldsLatest, - DetectionAlert8160 as DetectionAlertLatest, - WrappedFields8160 as WrappedFieldsLatest, - EqlBuildingBlockFields8160 as EqlBuildingBlockFieldsLatest, - EqlShellFields8160 as EqlShellFieldsLatest, - NewTermsFields8160 as NewTermsFieldsLatest, + Ancestor8180 as AncestorLatest, + BaseFields8180 as BaseFieldsLatest, + DetectionAlert8180 as DetectionAlertLatest, + WrappedFields8180 as WrappedFieldsLatest, + EqlBuildingBlockFields8180 as EqlBuildingBlockFieldsLatest, + EqlShellFields8180 as EqlShellFieldsLatest, + NewTermsFields8180 as NewTermsFieldsLatest, }; diff --git a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schedule.ts b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schedule.ts new file mode 100644 index 0000000000000..0177dd0b96db3 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schedule.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from '@kbn/zod'; +import { RuleIntervalFrom, RuleIntervalTo } from './common_attributes.gen'; +import { TimeDuration as TimeDurationSchema } from './time_duration'; + +export type RuleSchedule = z.infer; +export const RuleSchedule = z.object({ + interval: TimeDurationSchema({ allowedUnits: ['s', 'm', 'h'] }), + from: RuleIntervalFrom, + to: RuleIntervalTo, +}); + +/** + * Simpler version of RuleSchedule. It's only feasible when + * - `to` equals `now` (current moment in time) + * - `from` is less than `now` - `interval` + * + * Examples: + * + * - rule schedule: interval = 10m, from = now-15m, to = now + * simpler rule schedule: interval = 10m, lookback = 5m + * + * - rule schedule: interval = 1h, from = now-120m, to = now + * simpler rule schedule: interval = 10m, lookback = 5m + */ +export type SimpleRuleSchedule = z.infer; +export const SimpleRuleSchedule = z.object({ + /** + * Rule running interval in time duration format, e.g. `2m`, `3h` + */ + interval: TimeDurationSchema({ allowedUnits: ['s', 'm', 'h'] }), + /** + * Non-negative additional source events look-back to compensate rule execution delays + * in time duration format, e.g. `2m`, `3h`. + * + * Having `interval`, `from` and `to` and can be calculated as + * + * lookback = now - `interval` - `from`, where `now` is the current moment in time + * + * In the other words rules use time range [now - interval - lookback, now] + * to select source events for analysis. + */ + lookback: TimeDurationSchema({ allowedUnits: ['s', 'm', 'h'] }), +}); diff --git a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/rule_schema/to_simple_rule_schedule.test.ts b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/rule_schema/to_simple_rule_schedule.test.ts new file mode 100644 index 0000000000000..c2383090a466a --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/rule_schema/to_simple_rule_schedule.test.ts @@ -0,0 +1,105 @@ +/* + * 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 { toSimpleRuleSchedule } from './to_simple_rule_schedule'; + +describe('toSimpleRuleSchedule', () => { + it.each([ + [ + { interval: '10s', from: 'now-20s', to: 'now' }, + { interval: '10s', lookback: '10s' }, + ], + [ + { interval: '10m', from: 'now-30m', to: 'now' }, + { interval: '10m', lookback: '20m' }, + ], + [ + { interval: '1h', from: 'now-3h', to: 'now' }, + { interval: '1h', lookback: '2h' }, + ], + [ + { interval: '60s', from: 'now-2m', to: 'now' }, + { interval: '60s', lookback: '1m' }, + ], + [ + { interval: '60s', from: 'now-2h', to: 'now' }, + { interval: '60s', lookback: '119m' }, + ], + [ + { interval: '60m', from: 'now-3h', to: 'now' }, + { interval: '60m', lookback: '2h' }, + ], + [ + { interval: '3600s', from: 'now-5h', to: 'now' }, + { interval: '3600s', lookback: '4h' }, + ], + [ + { interval: '1m', from: 'now-120s', to: 'now' }, + { interval: '1m', lookback: '1m' }, + ], + [ + { interval: '1h', from: 'now-7200s', to: 'now' }, + { interval: '1h', lookback: '1h' }, + ], + [ + { interval: '1h', from: 'now-120m', to: 'now' }, + { interval: '1h', lookback: '1h' }, + ], + [ + { interval: '90s', from: 'now-90s', to: 'now' }, + { interval: '90s', lookback: '0s' }, + ], + [ + { interval: '30m', from: 'now-30m', to: 'now' }, + { interval: '30m', lookback: '0s' }, + ], + [ + { interval: '1h', from: 'now-1h', to: 'now' }, + { interval: '1h', lookback: '0s' }, + ], + [ + { interval: '60s', from: 'now-1m', to: 'now' }, + { interval: '60s', lookback: '0s' }, + ], + [ + { interval: '60m', from: 'now-1h', to: 'now' }, + { interval: '60m', lookback: '0s' }, + ], + [ + { interval: '1m', from: 'now-60s', to: 'now' }, + { interval: '1m', lookback: '0s' }, + ], + [ + { interval: '1h', from: 'now-60m', to: 'now' }, + { interval: '1h', lookback: '0s' }, + ], + [ + { interval: '1h', from: 'now-3600s', to: 'now' }, + { interval: '1h', lookback: '0s' }, + ], + [ + { interval: '0s', from: 'now', to: 'now' }, + { interval: '0s', lookback: '0s' }, + ], + ])('transforms %j to simple rule schedule', (fullRuleSchedule, expected) => { + const result = toSimpleRuleSchedule(fullRuleSchedule); + + expect(result).toEqual(expected); + }); + + it.each([ + [{ interval: 'invalid', from: 'now-11m', to: 'now' }], + [{ interval: '10m', from: 'invalid', to: 'now' }], + [{ interval: '10m', from: 'now-11m', to: 'invalid' }], + [{ interval: '10m', from: 'now-11m', to: 'now-1m' }], + [{ interval: '10m', from: 'now-5m', to: 'now' }], + ])('returns "undefined" for %j', (fullRuleSchedule) => { + const result = toSimpleRuleSchedule(fullRuleSchedule); + + expect(result).toBeUndefined(); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/rule_schema/to_simple_rule_schedule.ts b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/rule_schema/to_simple_rule_schedule.ts new file mode 100644 index 0000000000000..5227099e63111 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/rule_schema/to_simple_rule_schedule.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { calcDateMathDiff } from '@kbn/securitysolution-utils/date_math'; +import { TimeDuration as TimeDurationUtil } from '@kbn/securitysolution-utils/time_duration'; +import type { RuleSchedule, SimpleRuleSchedule } from './rule_schedule'; + +/** + * Transforms RuleSchedule to SimpleRuleSchedule by replacing `from` and `to` with `lookback`. + * + * The transformation is only possible when `to` equals to `now` and result `lookback` is non-negative. + */ +export function toSimpleRuleSchedule(ruleSchedule: RuleSchedule): SimpleRuleSchedule | undefined { + if (ruleSchedule.to !== 'now') { + return undefined; + } + + const lookBackMs = calcDateMathDiff(ruleSchedule.from, `now-${ruleSchedule.interval}`); + + if (lookBackMs === undefined || lookBackMs < 0) { + return undefined; + } + + return { + interval: ruleSchedule.interval, + lookback: TimeDurationUtil.fromMilliseconds(lookBackMs).toString(), + }; +} diff --git a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/prebuilt_rules/model/diff/diffable_rule/diffable_field_types.ts b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/prebuilt_rules/model/diff/diffable_rule/diffable_field_types.ts index 6262fd0e579e7..c41e950dab0ea 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/prebuilt_rules/model/diff/diffable_rule/diffable_field_types.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/prebuilt_rules/model/diff/diffable_rule/diffable_field_types.ts @@ -23,7 +23,6 @@ import { TimestampOverride, TimestampOverrideFallbackDisabled, } from '../../../../model/rule_schema'; -import { TimeDuration } from '../../../../model/rule_schema/time_duration'; // ------------------------------------------------------------------------------------------------- // Rule data source @@ -92,15 +91,6 @@ export const RuleEsqlQuery = z.object({ language: z.literal('esql'), }); -// ------------------------------------------------------------------------------------------------- -// Rule schedule - -export type RuleSchedule = z.infer; -export const RuleSchedule = z.object({ - interval: TimeDuration({ allowedUnits: ['s', 'm', 'h'] }), - lookback: TimeDuration({ allowedUnits: ['s', 'm', 'h'] }), -}); - // ------------------------------------------------------------------------------------------------- // Rule name override diff --git a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/prebuilt_rules/model/diff/diffable_rule/diffable_rule.ts b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/prebuilt_rules/model/diff/diffable_rule/diffable_rule.ts index 428d30495722a..a7fd0d53078bb 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/prebuilt_rules/model/diff/diffable_rule/diffable_rule.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/prebuilt_rules/model/diff/diffable_rule/diffable_rule.ts @@ -45,10 +45,10 @@ import { RuleEsqlQuery, RuleKqlQuery, RuleNameOverrideObject, - RuleSchedule, TimelineTemplateReference, TimestampOverrideObject, } from './diffable_field_types'; +import { RuleSchedule } from '../../../../model/rule_schema/rule_schedule'; export type DiffableCommonFields = z.infer; export const DiffableCommonFields = z.object({ diff --git a/x-pack/solutions/security/plugins/security_solution/common/api/quickstart_client.gen.ts b/x-pack/solutions/security/plugins/security_solution/common/api/quickstart_client.gen.ts index 50c9a2d4a913e..a57be4b8f0680 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/api/quickstart_client.gen.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/api/quickstart_client.gen.ts @@ -386,8 +386,6 @@ import type { InstallMigrationRulesRequestParamsInput, InstallMigrationRulesRequestBodyInput, InstallMigrationRulesResponse, - InstallTranslatedMigrationRulesRequestParamsInput, - InstallTranslatedMigrationRulesResponse, StartRuleMigrationRequestParamsInput, StartRuleMigrationRequestBodyInput, StartRuleMigrationResponse, @@ -1736,24 +1734,6 @@ finalize it. }) .catch(catchAxiosErrorFormatAndThrow); } - /** - * Installs all translated migration rules - */ - async installTranslatedMigrationRules(props: InstallTranslatedMigrationRulesProps) { - this.log.info(`${new Date().toISOString()} Calling API InstallTranslatedMigrationRules`); - return this.kbnClient - .request({ - path: replaceParams( - '/internal/siem_migrations/rules/{migration_id}/install_translated', - props.params - ), - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '1', - }, - method: 'POST', - }) - .catch(catchAxiosErrorFormatAndThrow); - } async internalUploadAssetCriticalityRecords(props: InternalUploadAssetCriticalityRecordsProps) { this.log.info(`${new Date().toISOString()} Calling API InternalUploadAssetCriticalityRecords`); return this.kbnClient @@ -2541,9 +2521,6 @@ export interface InstallMigrationRulesProps { export interface InstallPrepackedTimelinesProps { body: InstallPrepackedTimelinesRequestBodyInput; } -export interface InstallTranslatedMigrationRulesProps { - params: InstallTranslatedMigrationRulesRequestParamsInput; -} export interface InternalUploadAssetCriticalityRecordsProps { attachment: FormData; } diff --git a/x-pack/solutions/security/plugins/security_solution/common/api/search_strategy/index.ts b/x-pack/solutions/security/plugins/security_solution/common/api/search_strategy/index.ts index f3e70d9f12792..c1e509582f406 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/api/search_strategy/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/api/search_strategy/index.ts @@ -45,6 +45,7 @@ import { userAuthenticationsSchema, usersSchema, } from './users/users'; +import { observedServiceDetailsSchema } from './services'; export * from './first_seen_last_seen/first_seen_last_seen'; @@ -52,6 +53,8 @@ export * from './hosts/hosts'; export * from './users/users'; +export * from './services'; + export * from './network/network'; export * from './related_entities/related_entities'; @@ -76,6 +79,7 @@ export const searchStrategyRequestSchema = z.discriminatedUnion('factoryQueryTyp observedUserDetailsSchema, managedUserDetailsSchema, userAuthenticationsSchema, + observedServiceDetailsSchema, riskScoreRequestOptionsSchema, riskScoreKpiRequestOptionsSchema, relatedHostsRequestOptionsSchema, diff --git a/x-pack/solutions/security/plugins/security_solution/common/api/search_strategy/model/factory_query_type.ts b/x-pack/solutions/security/plugins/security_solution/common/api/search_strategy/model/factory_query_type.ts index 48a4d06575334..1f97e6cda2038 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/api/search_strategy/model/factory_query_type.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/api/search_strategy/model/factory_query_type.ts @@ -19,6 +19,10 @@ export enum UsersQueries { authentications = 'authentications', } +export enum ServicesQueries { + observedDetails = 'observedServiceDetails', +} + export enum NetworkQueries { details = 'networkDetails', dns = 'dns', @@ -51,6 +55,7 @@ export enum RelatedEntitiesQueries { export type FactoryQueryTypes = | HostsQueries | UsersQueries + | ServicesQueries | NetworkQueries | EntityRiskQueries | CtiQueries diff --git a/x-pack/solutions/security/plugins/security_solution/common/api/search_strategy/services/index.ts b/x-pack/solutions/security/plugins/security_solution/common/api/search_strategy/services/index.ts new file mode 100644 index 0000000000000..6ba96ca8a1fcc --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/common/api/search_strategy/services/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './observed_details'; diff --git a/x-pack/solutions/security/plugins/security_solution/common/api/search_strategy/services/observed_details.ts b/x-pack/solutions/security/plugins/security_solution/common/api/search_strategy/services/observed_details.ts new file mode 100644 index 0000000000000..9c01b6ebc15de --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/common/api/search_strategy/services/observed_details.ts @@ -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 { z } from '@kbn/zod'; + +import { requestBasicOptionsSchema } from '../model/request_basic_options'; +import { inspect } from '../model/inspect'; +import { timerange } from '../model/timerange'; +import { ServicesQueries } from '../model/factory_query_type'; + +export const observedServiceDetailsSchema = requestBasicOptionsSchema.extend({ + serviceName: z.string(), + skip: z.boolean().optional(), + timerange, + inspect, + factoryQueryType: z.literal(ServicesQueries.observedDetails), +}); + +export type ObservedServiceDetailsRequestOptionsInput = z.input< + typeof observedServiceDetailsSchema +>; + +export type ObservedServiceDetailsRequestOptions = z.infer; diff --git a/x-pack/solutions/security/plugins/security_solution/common/constants.ts b/x-pack/solutions/security/plugins/security_solution/common/constants.ts index 159dae027faee..aa3f2d0d5c096 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/constants.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/constants.ts @@ -23,7 +23,10 @@ export const ASSET_INVENTORY_FEATURE_ID = 'securitySolutionAssetInventory' as co export const ASSISTANT_FEATURE_ID = 'securitySolutionAssistant' as const; export const ATTACK_DISCOVERY_FEATURE_ID = 'securitySolutionAttackDiscovery' as const; export const CASES_FEATURE_ID = 'securitySolutionCasesV2' as const; +export const TIMELINE_FEATURE_ID = 'securitySolutionTimeline' as const; +export const NOTES_FEATURE_ID = 'securitySolutionNotes' as const; export const SERVER_APP_ID = 'siem' as const; +export const SECURITY_FEATURE_ID = 'siemV2' as const; export const APP_NAME = 'Security' as const; export const APP_ICON = 'securityAnalyticsApp' as const; export const APP_ICON_SOLUTION = 'logoSecurity' as const; @@ -67,7 +70,6 @@ export const ENDPOINT_METRICS_INDEX = '.ds-metrics-endpoint.metrics-*' as const; export const DEFAULT_RULE_REFRESH_INTERVAL_ON = true as const; export const DEFAULT_RULE_REFRESH_INTERVAL_VALUE = 60000 as const; // ms export const DEFAULT_RULE_NOTIFICATION_QUERY_SIZE = 100 as const; -export const SECURITY_FEATURE_ID = 'Security' as const; export const SECURITY_TAG_NAME = 'Security Solution' as const; export const SECURITY_TAG_DESCRIPTION = 'Security Solution auto-generated tag' as const; export const DEFAULT_SPACE_ID = 'default' as const; diff --git a/x-pack/solutions/security/plugins/security_solution/common/detection_engine/prebuilt_rules/diff/extract_rule_schedule.test.ts b/x-pack/solutions/security/plugins/security_solution/common/detection_engine/prebuilt_rules/diff/extract_rule_schedule.test.ts index 7c03aae9a012c..7781041efedc7 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/detection_engine/prebuilt_rules/diff/extract_rule_schedule.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/detection_engine/prebuilt_rules/diff/extract_rule_schedule.test.ts @@ -5,14 +5,23 @@ * 2.0. */ -import { getRulesSchemaMock } from '../../../api/detection_engine/model/rule_schema/mocks'; +import type { RuleResponse } from '../../../api/detection_engine'; import { extractRuleSchedule } from './extract_rule_schedule'; describe('extractRuleSchedule', () => { - it('normalizes lookback strings to seconds', () => { - const mockRule = { ...getRulesSchemaMock(), from: 'now-6m', interval: '5m', to: 'now' }; - const normalizedRuleSchedule = extractRuleSchedule(mockRule); + it('returns rule schedule', () => { + const ruleSchedule = extractRuleSchedule({ + from: 'now-6m', + interval: '5m', + to: 'now', + } as RuleResponse); - expect(normalizedRuleSchedule).toEqual({ interval: '5m', lookback: '60s' }); + expect(ruleSchedule).toEqual({ interval: '5m', from: 'now-6m', to: 'now' }); + }); + + it('returns default values', () => { + const ruleSchedule = extractRuleSchedule({} as RuleResponse); + + expect(ruleSchedule).toEqual({ interval: '5m', from: 'now-6m', to: 'now' }); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/common/detection_engine/prebuilt_rules/diff/extract_rule_schedule.ts b/x-pack/solutions/security/plugins/security_solution/common/detection_engine/prebuilt_rules/diff/extract_rule_schedule.ts index 7a128c24492ab..25a4fe81c3e3d 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/detection_engine/prebuilt_rules/diff/extract_rule_schedule.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/detection_engine/prebuilt_rules/diff/extract_rule_schedule.ts @@ -5,63 +5,19 @@ * 2.0. */ -import moment from 'moment'; -import dateMath from '@elastic/datemath'; -import { parseDuration } from '@kbn/alerting-plugin/common'; - +import { TimeDuration } from '@kbn/securitysolution-utils/time_duration'; +import { normalizeDateMath } from '@kbn/securitysolution-utils/date_math'; +import type { RuleSchedule } from '../../../api/detection_engine/model/rule_schema/rule_schedule'; import type { RuleResponse } from '../../../api/detection_engine/model/rule_schema'; -import type { RuleSchedule } from '../../../api/detection_engine/prebuilt_rules'; export const extractRuleSchedule = (rule: RuleResponse): RuleSchedule => { - const interval = rule.interval ?? '5m'; + const interval = TimeDuration.parse(rule.interval) ?? new TimeDuration(5, 'm'); const from = rule.from ?? 'now-6m'; const to = rule.to ?? 'now'; - const intervalDuration = parseInterval(interval); - const driftToleranceDuration = parseDriftTolerance(from, to); - - if (intervalDuration == null) { - return { - interval: `Cannot parse: interval="${interval}"`, - lookback: `Cannot calculate due to invalid interval`, - }; - } - - if (driftToleranceDuration == null) { - return { - interval, - lookback: `Cannot parse: from="${from}", to="${to}"`, - }; - } - - const lookbackDuration = moment.duration().add(driftToleranceDuration).subtract(intervalDuration); - const lookback = `${lookbackDuration.asSeconds()}s`; - - return { interval, lookback }; -}; - -const parseInterval = (intervalString: string): moment.Duration | null => { - try { - const milliseconds = parseDuration(intervalString); - return moment.duration(milliseconds); - } catch (e) { - return null; - } -}; - -const parseDriftTolerance = (from: string, to: string): moment.Duration | null => { - const now = new Date(); - const fromDate = parseDateMathString(from, now); - const toDate = parseDateMathString(to, now); - - if (fromDate == null || toDate == null) { - return null; - } - - return moment.duration(toDate.diff(fromDate)); -}; - -const parseDateMathString = (dateMathString: string, now: Date): moment.Moment | null => { - const parsedDate = dateMath.parse(dateMathString, { forceNow: now }); - return parsedDate != null && parsedDate.isValid() ? parsedDate : null; + return { + interval: interval.toString(), + from: normalizeDateMath(from), + to: normalizeDateMath(to), + }; }; diff --git a/x-pack/solutions/security/plugins/security_solution/common/endpoint/types/workflow_insights.ts b/x-pack/solutions/security/plugins/security_solution/common/endpoint/types/workflow_insights.ts index 3212193c981cb..0fc2ec83139dd 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/endpoint/types/workflow_insights.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/endpoint/types/workflow_insights.ts @@ -61,6 +61,7 @@ export interface SecurityWorkflowInsight { metadata: { notes?: Record; message_variables?: string[]; + display_name?: string; }; } diff --git a/x-pack/solutions/security/plugins/security_solution/common/field_maps/8.18.0/alerts.ts b/x-pack/solutions/security/plugins/security_solution/common/field_maps/8.18.0/alerts.ts new file mode 100644 index 0000000000000..7c305f8506282 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/common/field_maps/8.18.0/alerts.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 { alertsFieldMap8160 } from '../8.16.0'; +import { + ALERT_SERVICE_CRITICALITY, + ALERT_SERVICE_RISK_SCORE_CALCULATED_LEVEL, + ALERT_SERVICE_RISK_SCORE_CALCULATED_SCORE_NORM, +} from '../field_names'; + +export const alertsFieldMap8180 = { + ...alertsFieldMap8160, + /** + * Stores the criticality level for the service, as determined by analysts, in relation to the alert. + * The Criticality level is copied from the asset criticality index. + */ + [ALERT_SERVICE_CRITICALITY]: { + type: 'keyword', + array: false, + required: false, + }, + + /** + * Stores the risk score level and score_norm level for the service, as determined by the Risk Engine, in relation to the alert. + * The Risk score is copied from the risk score index. + */ + [ALERT_SERVICE_RISK_SCORE_CALCULATED_LEVEL]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_SERVICE_RISK_SCORE_CALCULATED_SCORE_NORM]: { + type: 'float', + array: false, + required: false, + }, +} as const; + +export type AlertsFieldMap8180 = typeof alertsFieldMap8180; diff --git a/x-pack/solutions/security/plugins/security_solution/common/field_maps/8.18.0/index.ts b/x-pack/solutions/security/plugins/security_solution/common/field_maps/8.18.0/index.ts new file mode 100644 index 0000000000000..9b07c180f513f --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/common/field_maps/8.18.0/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { AlertsFieldMap8180 } from './alerts'; +import { alertsFieldMap8180 } from './alerts'; +export type { AlertsFieldMap8180 }; +export { alertsFieldMap8180 }; diff --git a/x-pack/solutions/security/plugins/security_solution/common/field_maps/field_names.ts b/x-pack/solutions/security/plugins/security_solution/common/field_maps/field_names.ts index b8ef2e61fb390..fa3407367b247 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/field_maps/field_names.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/field_maps/field_names.ts @@ -28,12 +28,16 @@ export const LEGACY_ALERT_USER_CRITICALITY = `${ALERT_NAMESPACE}.user.criticalit export const ALERT_HOST_CRITICALITY = `host.asset.criticality` as const; export const ALERT_USER_CRITICALITY = `user.asset.criticality` as const; +export const ALERT_SERVICE_CRITICALITY = `service.asset.criticality` as const; export const ALERT_HOST_RISK_SCORE_CALCULATED_LEVEL = `host.risk.calculated_level` as const; export const ALERT_HOST_RISK_SCORE_CALCULATED_SCORE_NORM = `host.risk.calculated_score_norm` as const; export const ALERT_USER_RISK_SCORE_CALCULATED_LEVEL = `user.risk.calculated_level` as const; export const ALERT_USER_RISK_SCORE_CALCULATED_SCORE_NORM = `user.risk.calculated_score_norm` as const; +export const ALERT_SERVICE_RISK_SCORE_CALCULATED_LEVEL = `service.risk.calculated_level` as const; +export const ALERT_SERVICE_RISK_SCORE_CALCULATED_SCORE_NORM = + `service.risk.calculated_score_norm` as const; export const ALERT_ORIGINAL_EVENT = `${ALERT_NAMESPACE}.original_event` as const; export const ALERT_ORIGINAL_EVENT_ACTION = `${ALERT_ORIGINAL_EVENT}.action` as const; diff --git a/x-pack/solutions/security/plugins/security_solution/common/field_maps/index.ts b/x-pack/solutions/security/plugins/security_solution/common/field_maps/index.ts index 5080ff2660533..f992f78eedb76 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/field_maps/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/field_maps/index.ts @@ -4,10 +4,9 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -import type { AlertsFieldMap8160 } from './8.16.0'; -import { alertsFieldMap8160 } from './8.16.0'; +import type { AlertsFieldMap8180 } from './8.18.0'; +import { alertsFieldMap8180 } from './8.18.0'; import type { RulesFieldMap } from './8.0.0/rules'; import { rulesFieldMap } from './8.0.0/rules'; -export type { AlertsFieldMap8160 as AlertsFieldMap, RulesFieldMap }; -export { alertsFieldMap8160 as alertsFieldMap, rulesFieldMap }; +export type { AlertsFieldMap8180 as AlertsFieldMap, RulesFieldMap }; +export { alertsFieldMap8180 as alertsFieldMap, rulesFieldMap }; diff --git a/x-pack/solutions/security/plugins/security_solution/common/index.ts b/x-pack/solutions/security/plugins/security_solution/common/index.ts index 7c240b39554a6..7bd4c019a6d15 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/index.ts @@ -10,6 +10,7 @@ export { APP_ID, CASES_FEATURE_ID, SERVER_APP_ID, + SECURITY_FEATURE_ID, APP_PATH, MANAGE_PATH, ADD_DATA_PATH, diff --git a/x-pack/solutions/security/plugins/security_solution/common/search_strategy/security_solution/index.ts b/x-pack/solutions/security/plugins/security_solution/common/search_strategy/security_solution/index.ts index cc84119398909..49d0e88c1b064 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/search_strategy/security_solution/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/search_strategy/security_solution/index.ts @@ -75,6 +75,8 @@ import type { NetworkTopNFlowRequestOptionsInput, NetworkUsersRequestOptions, NetworkUsersRequestOptionsInput, + ObservedServiceDetailsRequestOptions, + ObservedServiceDetailsRequestOptionsInput, ObservedUserDetailsRequestOptions, ObservedUserDetailsRequestOptionsInput, RelatedHostsRequestOptions, @@ -85,6 +87,7 @@ import type { RiskScoreKpiRequestOptionsInput, RiskScoreRequestOptions, RiskScoreRequestOptionsInput, + ServicesQueries, ThreatIntelSourceRequestOptions, ThreatIntelSourceRequestOptionsInput, UserAuthenticationsRequestOptions, @@ -97,12 +100,14 @@ import type { EntityType, RiskScoreStrategyResponse, } from './risk_score'; +import type { ObservedServiceDetailsStrategyResponse } from './services'; export * from './cti'; export * from './hosts'; export * from './risk_score'; export * from './network'; export * from './users'; +export * from './services'; export * from './first_last_seen'; export * from './related_entities'; @@ -110,6 +115,7 @@ export type FactoryQueryTypes = | HostsQueries | UsersQueries | NetworkQueries + | ServicesQueries | EntityRiskQueries | CtiQueries | typeof FirstLastSeenQuery @@ -133,6 +139,8 @@ export type StrategyResponseType = T extends HostsQ ? UserAuthenticationsStrategyResponse : T extends UsersQueries.users ? UsersStrategyResponse + : T extends ServicesQueries.observedDetails + ? ObservedServiceDetailsStrategyResponse : T extends NetworkQueries.details ? NetworkDetailsStrategyResponse : T extends NetworkQueries.dns @@ -183,6 +191,8 @@ export type StrategyRequestInputType = T extends Ho ? ManagedUserDetailsRequestOptionsInput : T extends UsersQueries.users ? UsersRequestOptionsInput + : T extends ServicesQueries.observedDetails + ? ObservedServiceDetailsRequestOptionsInput : T extends NetworkQueries.details ? NetworkDetailsRequestOptionsInput : T extends NetworkQueries.dns @@ -233,6 +243,8 @@ export type StrategyRequestType = T extends HostsQu ? ManagedUserDetailsRequestOptions : T extends UsersQueries.users ? UsersRequestOptions + : T extends ServicesQueries.observedDetails + ? ObservedServiceDetailsRequestOptions : T extends NetworkQueries.details ? NetworkDetailsRequestOptions : T extends NetworkQueries.dns diff --git a/x-pack/solutions/security/plugins/security_solution/common/search_strategy/security_solution/services/common/index.ts b/x-pack/solutions/security/plugins/security_solution/common/search_strategy/security_solution/services/common/index.ts new file mode 100644 index 0000000000000..bc26c89cbc737 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/common/search_strategy/security_solution/services/common/index.ts @@ -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 type { ServiceEcs } from '@kbn/securitysolution-ecs'; +import type { CommonFields, Maybe } from '../../..'; + +export interface ServiceItem { + service?: Maybe; +} + +export interface ServiceAggEsItem { + service_id?: ServiceBuckets; + service_name?: ServiceBuckets; + service_address?: ServiceBuckets; + service_environment?: ServiceBuckets; + service_ephemeral_id?: ServiceBuckets; + service_node_name?: ServiceBuckets; + service_node_role?: ServiceBuckets; + service_node_roles?: ServiceBuckets; + service_state?: ServiceBuckets; + service_type?: ServiceBuckets; + service_version?: ServiceBuckets; +} + +export interface ServiceBuckets { + buckets: Array<{ + key: string; + doc_count: number; + }>; +} + +export interface AllServicesAggEsItem { + key: string; + domain?: ServicesDomainHitsItem; + lastSeen?: { value_as_string: string }; +} + +type ServiceFields = CommonFields & + Partial<{ + [Property in keyof ServiceEcs as `service.${Property}`]: unknown[]; + }>; + +interface ServicesDomainHitsItem { + hits: { + hits: Array<{ + fields: ServiceFields; + }>; + }; +} diff --git a/x-pack/solutions/security/plugins/security_solution/common/search_strategy/security_solution/services/index.ts b/x-pack/solutions/security/plugins/security_solution/common/search_strategy/security_solution/services/index.ts new file mode 100644 index 0000000000000..f4e899539ec4b --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/common/search_strategy/security_solution/services/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './observed_details'; +export * from './common'; + +export { ServicesQueries } from '../../../api/search_strategy'; diff --git a/x-pack/solutions/security/plugins/security_solution/common/search_strategy/security_solution/services/observed_details/index.ts b/x-pack/solutions/security/plugins/security_solution/common/search_strategy/security_solution/services/observed_details/index.ts new file mode 100644 index 0000000000000..1973e5b36e5f7 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/common/search_strategy/security_solution/services/observed_details/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { IEsSearchResponse } from '@kbn/search-types'; + +import type { Inspect, Maybe } from '../../../common'; +import type { ServiceItem } from '../common'; + +export interface ObservedServiceDetailsStrategyResponse extends IEsSearchResponse { + serviceDetails: ServiceItem; + inspect?: Maybe; +} diff --git a/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/constants.ts b/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/constants.ts index 409df3e97a9b6..16cd4365d56bc 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/constants.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/constants.ts @@ -22,8 +22,6 @@ export const SIEM_RULE_MIGRATION_TRANSLATION_STATS_PATH = `${SIEM_RULE_MIGRATION_PATH}/translation_stats` as const; export const SIEM_RULE_MIGRATION_STOP_PATH = `${SIEM_RULE_MIGRATION_PATH}/stop` as const; export const SIEM_RULE_MIGRATION_INSTALL_PATH = `${SIEM_RULE_MIGRATION_PATH}/install` as const; -export const SIEM_RULE_MIGRATION_INSTALL_TRANSLATED_PATH = - `${SIEM_RULE_MIGRATION_PATH}/install_translated` as const; export const SIEM_RULE_MIGRATIONS_PREBUILT_RULES_PATH = `${SIEM_RULE_MIGRATION_PATH}/prebuilt_rules` as const; @@ -60,22 +58,7 @@ export const DEFAULT_TRANSLATION_RISK_SCORE = 21; export const DEFAULT_TRANSLATION_SEVERITY: Severity = 'low'; export const DEFAULT_TRANSLATION_FIELDS = { - risk_score: DEFAULT_TRANSLATION_RISK_SCORE, - severity: DEFAULT_TRANSLATION_SEVERITY, from: 'now-360s', to: 'now', interval: '5m', } as const; - -export enum AuthorFilter { - ELASTIC = 'elastic', - CUSTOM = 'custom', -} - -export enum StatusFilter { - INSTALLED = 'installed', - TRANSLATED = 'translated', - PARTIALLY_TRANSLATED = 'partially_translated', - UNTRANSLATABLE = 'untranslatable', - FAILED = 'failed', -} diff --git a/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/model/api/rules/rule_migration.gen.ts b/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/model/api/rules/rule_migration.gen.ts index 5f659149e594a..a03453b318aec 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/model/api/rules/rule_migration.gen.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/model/api/rules/rule_migration.gen.ts @@ -193,7 +193,7 @@ export type InstallMigrationRulesRequestParamsInput = z.input< export type InstallMigrationRulesRequestBody = z.infer; export const InstallMigrationRulesRequestBody = z.object({ - ids: z.array(NonEmptyString), + ids: z.array(NonEmptyString).optional(), /** * Indicates whether installed rules should be enabled */ @@ -206,29 +206,9 @@ export type InstallMigrationRulesRequestBodyInput = z.input< export type InstallMigrationRulesResponse = z.infer; export const InstallMigrationRulesResponse = z.object({ /** - * Indicates rules migrations have been installed. + * Indicates the number of successfully installed migration rules. */ - installed: z.boolean(), -}); - -export type InstallTranslatedMigrationRulesRequestParams = z.infer< - typeof InstallTranslatedMigrationRulesRequestParams ->; -export const InstallTranslatedMigrationRulesRequestParams = z.object({ - migration_id: NonEmptyString, -}); -export type InstallTranslatedMigrationRulesRequestParamsInput = z.input< - typeof InstallTranslatedMigrationRulesRequestParams ->; - -export type InstallTranslatedMigrationRulesResponse = z.infer< - typeof InstallTranslatedMigrationRulesResponse ->; -export const InstallTranslatedMigrationRulesResponse = z.object({ - /** - * Indicates rules migrations have been installed. - */ - installed: z.boolean(), + installed: z.number(), }); export type StartRuleMigrationRequestParams = z.infer; diff --git a/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/model/api/rules/rule_migration.schema.yaml b/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/model/api/rules/rule_migration.schema.yaml index 3d656c686615e..e3d9933ce6e93 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/model/api/rules/rule_migration.schema.yaml +++ b/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/model/api/rules/rule_migration.schema.yaml @@ -237,8 +237,6 @@ paths: application/json: schema: type: object - required: - - ids properties: ids: type: array @@ -259,37 +257,8 @@ paths: - installed properties: installed: - type: boolean - description: Indicates rules migrations have been installed. - - /internal/siem_migrations/rules/{migration_id}/install_translated: - post: - summary: Installs all translated migration rules - operationId: InstallTranslatedMigrationRules - x-codegen-enabled: true - description: Installs all translated migration rules - tags: - - SIEM Rule Migrations - parameters: - - name: migration_id - in: path - required: true - schema: - description: The migration id to install translated rules for - $ref: '../../../../../common/api/model/primitives.schema.yaml#/components/schemas/NonEmptyString' - responses: - 200: - description: Indicates rules migrations have been installed correctly. - content: - application/json: - schema: - type: object - required: - - installed - properties: - installed: - type: boolean - description: Indicates rules migrations have been installed. + type: number + description: Indicates the number of successfully installed migration rules. /internal/siem_migrations/rules/{migration_id}/start: put: diff --git a/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/model/rule_migration.gen.ts b/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/model/rule_migration.gen.ts index 131d78394cda5..a81e264073ef9 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/model/rule_migration.gen.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/model/rule_migration.gen.ts @@ -90,6 +90,10 @@ export const ElasticRule = z.object({ * The migrated rule severity. */ severity: z.string().optional(), + /** + * The migrated rule risk_score value, integer between 0 and 100. + */ + risk_score: z.number().optional(), /** * The translated elastic query. */ @@ -103,9 +107,9 @@ export const ElasticRule = z.object({ */ prebuilt_rule_id: NonEmptyString.optional(), /** - * The Elastic integration ID found to be most relevant to the splunk rule. + * The IDs of the Elastic integrations suggested to be installed for this rule. */ - integration_id: z.string().optional(), + integration_ids: z.array(z.string()).optional(), /** * The Elastic rule id installed as a result. */ diff --git a/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/model/rule_migration.schema.yaml b/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/model/rule_migration.schema.yaml index 4443141db85b3..657d74eaee35b 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/model/rule_migration.schema.yaml +++ b/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/model/rule_migration.schema.yaml @@ -72,6 +72,9 @@ components: severity: type: string description: The migrated rule severity. + risk_score: + type: number + description: The migrated rule risk_score value, integer between 0 and 100. query: type: string description: The translated elastic query. @@ -83,9 +86,11 @@ components: prebuilt_rule_id: description: The Elastic prebuilt rule id matched. $ref: '../../../common/api/model/primitives.schema.yaml#/components/schemas/NonEmptyString' - integration_id: - type: string - description: The Elastic integration ID found to be most relevant to the splunk rule. + integration_ids: + type: array + description: The IDs of the Elastic integrations suggested to be installed for this rule. + items: + type: string id: description: The Elastic rule id installed as a result. $ref: '../../../common/api/model/primitives.schema.yaml#/components/schemas/NonEmptyString' diff --git a/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/rules/utils.ts b/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/rules/utils.ts index 8763e057052b5..b82fada3c725a 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/rules/utils.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/rules/utils.ts @@ -6,14 +6,24 @@ */ import type { Severity } from '../../api/detection_engine'; -import { DEFAULT_TRANSLATION_FIELDS, DEFAULT_TRANSLATION_SEVERITY } from '../constants'; +import { DEFAULT_TRANSLATION_FIELDS } from '../constants'; import type { ElasticRule, ElasticRulePartial } from '../model/rule_migration.gen'; export type MigrationPrebuiltRule = ElasticRulePartial & - Required>; + Required< + Pick< + ElasticRulePartial, + 'title' | 'description' | 'prebuilt_rule_id' | 'severity' | 'risk_score' + > + >; export type MigrationCustomRule = ElasticRulePartial & - Required>; + Required< + Pick< + ElasticRulePartial, + 'title' | 'description' | 'query' | 'query_language' | 'severity' | 'risk_score' + > + >; export const isMigrationPrebuiltRule = (rule?: ElasticRule): rule is MigrationPrebuiltRule => !!(rule?.title && rule?.description && rule?.prebuilt_rule_id); @@ -33,8 +43,8 @@ export const convertMigrationCustomRuleToSecurityRulePayload = ( name: rule.title, description: rule.description, enabled, - + severity: rule.severity as Severity, + risk_score: rule.risk_score, ...DEFAULT_TRANSLATION_FIELDS, - severity: (rule.severity as Severity) ?? DEFAULT_TRANSLATION_SEVERITY, }; }; diff --git a/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/types.ts b/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/types.ts new file mode 100644 index 0000000000000..7b275975695c7 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/common/siem_migrations/types.ts @@ -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 type { SiemMigrationStatus } from './constants'; + +export interface RuleMigrationFilters { + status?: SiemMigrationStatus | SiemMigrationStatus[]; + ids?: string[]; + installed?: boolean; + installable?: boolean; + prebuilt?: boolean; + failed?: boolean; + fullyTranslated?: boolean; + partiallyTranslated?: boolean; + untranslatable?: boolean; + searchTerm?: string; +} diff --git a/x-pack/solutions/security/plugins/security_solution/common/test/ess_roles.json b/x-pack/solutions/security/plugins/security_solution/common/test/ess_roles.json index 361d5d4321756..6259330cc2899 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/test/ess_roles.json +++ b/x-pack/solutions/security/plugins/security_solution/common/test/ess_roles.json @@ -27,10 +27,12 @@ { "feature": { "ml": ["read"], - "siem": ["read", "read_alerts"], + "siemV2": ["read", "read_alerts"], "securitySolutionAssistant": ["none"], "securitySolutionAttackDiscovery": ["none"], "securitySolutionCasesV2": ["read"], + "securitySolutionTimeline": ["read"], + "securitySolutionNotes": ["read"], "actions": ["read"], "builtInAlerts": ["read"] }, @@ -76,10 +78,12 @@ { "feature": { "ml": ["read"], - "siem": ["all", "read_alerts", "crud_alerts"], + "siemV2": ["all", "read_alerts", "crud_alerts"], "securitySolutionAssistant": ["all"], "securitySolutionAttackDiscovery": ["all"], "securitySolutionCasesV2": ["all"], + "securitySolutionTimeline": ["read"], + "securitySolutionNotes": ["read"], "actions": ["read"], "builtInAlerts": ["all"] }, @@ -125,10 +129,12 @@ { "feature": { "ml": ["read"], - "siem": ["all", "read_alerts", "crud_alerts"], + "siemV2": ["all", "read_alerts", "crud_alerts"], "securitySolutionAssistant": ["all"], "securitySolutionAttackDiscovery": ["all"], "securitySolutionCasesV2": ["all"], + "securitySolutionTimeline": ["all"], + "securitySolutionNotes": ["all"], "builtInAlerts": ["all"] }, "spaces": ["*"], @@ -146,7 +152,115 @@ "kibana": [ { "feature": { - "siem": ["read"] + "siemV2": ["read"] + }, + "spaces": ["*"], + "base": [] + } + ] + }, + "timeline_none": { + "name": "timeline_none", + "elasticsearch": { + "cluster": [], + "indices": [ + { + "names": [ + "apm-*-transaction*", + "traces-apm*", + "auditbeat-*", + "endgame-*", + "filebeat-*", + "logs-*", + "packetbeat-*", + "winlogbeat-*", + ".lists*", + ".items*", + ".asset-criticality.asset-criticality-*" + ], + "privileges": ["read", "write"] + }, + { + "names": [ + ".alerts-security*", + ".preview.alerts-security*", + ".internal.preview.alerts-security*", + ".siem-signals-*" + ], + "privileges": ["read", "write", "manage"] + }, + { + "names": ["metrics-endpoint.metadata_current_*", ".fleet-agents*", ".fleet-actions*"], + "privileges": ["read"] + } + ], + "run_as": [] + }, + "kibana": [ + { + "feature": { + "ml": ["read"], + "siemV2": ["all", "read_alerts", "crud_alerts"], + "securitySolutionAssistant": ["all"], + "securitySolutionAttackDiscovery": ["all"], + "securitySolutionCasesV2": ["all"], + "securitySolutionNotes": ["all"], + "actions": ["all"], + "builtInAlerts": ["all"] + }, + "spaces": ["*"], + "base": [] + } + ] + }, + "notes_none": { + "name": "notes_none", + "elasticsearch": { + "cluster": [], + "indices": [ + { + "names": [ + "apm-*-transaction*", + "traces-apm*", + "auditbeat-*", + "endgame-*", + "filebeat-*", + "logs-*", + "packetbeat-*", + "winlogbeat-*", + ".lists*", + ".items*", + ".asset-criticality.asset-criticality-*" + ], + "privileges": ["read", "write"] + }, + { + "names": [ + ".alerts-security*", + ".preview.alerts-security*", + ".internal.preview.alerts-security*", + ".siem-signals-*" + ], + "privileges": ["read", "write", "manage"] + }, + { + "names": ["metrics-endpoint.metadata_current_*", ".fleet-agents*", ".fleet-actions*"], + "privileges": ["read"] + } + ], + "run_as": [] + }, + "kibana": [ + { + "feature": { + "ml": ["read"], + "siemV2": ["all", "read_alerts", "crud_alerts"], + "securitySolutionAssistant": ["all"], + "securitySolutionAttackDiscovery": ["all"], + "securitySolutionCasesV2": ["all"], + "securitySolutionTimeline": ["all"], + "actions": ["all"], + "builtInAlerts": ["all"] }, "spaces": ["*"], "base": [] diff --git a/x-pack/solutions/security/plugins/security_solution/common/test/index.ts b/x-pack/solutions/security/plugins/security_solution/common/test/index.ts index 277f54c78e6c5..b54e082bf2625 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/test/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/test/index.ts @@ -30,6 +30,8 @@ export enum ROLES { hunter = 'hunter', hunter_no_actions = 'hunter_no_actions', no_risk_engine_privileges = 'no_risk_engine_privileges', + timeline_none = 'timeline_none', + notes_none = 'notes_none', } /** diff --git a/x-pack/solutions/security/plugins/security_solution/common/types/header_actions/index.ts b/x-pack/solutions/security/plugins/security_solution/common/types/header_actions/index.ts index 29f0b608fe56b..14852edd8c864 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/types/header_actions/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/types/header_actions/index.ts @@ -114,6 +114,7 @@ export interface ActionProps { toggleShowNotes?: () => void; width?: number; disablePinAction?: boolean; + disableTimelineAction?: boolean; } interface AdditionalControlColumnProps { diff --git a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/exporting.md b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/exporting.md index f4cbc66779a81..3c9527a7329c9 100644 --- a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/exporting.md +++ b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/exporting.md @@ -1,8 +1,8 @@ -# Prebuilt Rule Export +# Detection Rule Export -This is a test plan for the exporting of prebuilt rules. This feature is an aspect of `Milestone 2` of the [Rule Immutability/Customization](https://github.com/elastic/security-team/issues/1974) epic. +This is a test plan for the exporting of prebuilt and custom rules. This feature is an aspect of `Milestone 3` of the [Rule Immutability/Customization](https://github.com/elastic/security-team/issues/1974) epic. -Status: `in progress`. +Status: `in progress`. ## Useful information @@ -22,42 +22,118 @@ Status: `in progress`. ### Core Functionality -#### Scenario: Exporting prebuilt rule individually +#### Scenario: Exporting prebuilt rule individually from rule details page + +**Automation**: 2 cypress tests. + ```Gherkin -Given a space with prebuilt rules installed -When the user selects "Export rule" from the "All actions" dropdown on the rule's page +Given a space with a rule installed +When the user selects "Export rule" from the "All actions" dropdown on the rule's detail page Then the rule should be exported as an NDJSON file And it should include an "immutable" field with a value of true And its "ruleSource" "type" should be "external" -And its "ruleSource" "isCustomized" value should depend on whether the rule was customized +And its "ruleSource" "isCustomized" value should be + +Examples: +| rule_type | is_customized | +| prebuilt customized | true | +| prebuilt non-customized | false | +``` + +#### Scenario: Exporting custom rule individually from rule details page + +**Automation**: 1 cypress test. + +```Gherkin +Given a space with a custom rule installed +When the user selects "Export rule" from the "All actions" dropdown on the rule's detail page +Then the rule should be exported as an NDJSON file +And it should include an "immutable" field with a value of false +And its "ruleSource" "type" should be "internal" +``` + +#### Scenario: Exporting prebuilt rule individually from rules management table + +**Automation**: 2 cypress tests. + +```Gherkin +Given a space with a rule installed +When the user selects "Export rule" from the rule's overflow dropdown on the rules management page +Then the rule should be exported as an NDJSON file +And it should include an "immutable" field with a value of true +And its "ruleSource" "type" should be "external" +And its "ruleSource" "isCustomized" value should be + +Examples: +| rule_type | is_customized | +| prebuilt customized | true | +| prebuilt non-customized | false | +``` + +#### Scenario: Exporting custom rule individually from rules management table + +**Automation**: 1 cypress test. + +```Gherkin +Given a space with a custom rule installed +When the user selects "Export rule" from the rule's overflow dropdown on the rules management page +Then the rule should be exported as an NDJSON file +And it should include an "immutable" field with a value of false +And its "ruleSource" "type" should be "internal" ``` #### Scenario: Exporting prebuilt rules in bulk + +**Automation**: 2 cypress tests. + ```Gherkin -Given a space with prebuilt rules installed -When the user selects prebuilt rules in the alerts table +Given a space with multiple rules installed +When the user selects rules in the rules table And chooses "Export" from bulk actions Then the selected rules should be exported as an NDJSON file And they should include an "immutable" field with a value of true And their "ruleSource" "type" should be "external" -And their "ruleSource" "isCustomized" should depend on whether the rule was customized +And their "ruleSource" "isCustomized" should depend be + +Examples: +| rule_type | is_customized | +| prebuilt customized | true | +| prebuilt non-customized | false | +``` + +#### Scenario: Exporting custom rules in bulk + +**Automation**: 1 cypress test. + +```Gherkin +Given a space with multiple custom rules installed +When the user selects rules in the rules table +And chooses "Export" from bulk actions +Then the selected rules should be exported as an NDJSON file +And they should include an "immutable" field with a value of false +And their "ruleSource" "type" should be "internal" ``` #### Scenario: Exporting both prebuilt and custom rules in bulk + +**Automation**: 1 cypress test. + ```Gherkin -Given a space with prebuilt and custom rules installed -When the user selects prebuilt rules in the alerts table +Given a space with customized prebuilt, non-customized prebuilt and custom rules installed +When the user selects rules from each type in the rules table And chooses "Export" from bulk actions Then the selected rules should be exported as an NDJSON file And the prebuilt rules should include an "immutable" field with a value of true And the custom rules should include an "immutable" field with a value of false And the prebuilt rules' "ruleSource" "type" should be "external" And the custom rules' "ruleSource" "type" should be "internal" +And the customized prebuilt rules' "isCustomized" value should be true ``` ### Error Handling #### Scenario: Exporting beyond the export limit + ```Gherkin Given a space with prebuilt and custom rules installed And the number of rules is greater than the export limit (defaults to 10_000) diff --git a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/importing.md b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/importing.md index 0c947d0a52b95..b1765b948e6fd 100644 --- a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/importing.md +++ b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/importing.md @@ -1,6 +1,6 @@ -# Prebuilt Rule Import +# Detections Rule Import -This is a test plan for the importing of prebuilt rules. This feature is an aspect of `Milestone 2` of the [Rule Immutability/Customization](https://github.com/elastic/security-team/issues/1974) epic. +This is a test plan for the importing of prebuilt and custom rules. This feature is an aspect of `Milestone 3` of the [Rule Immutability/Customization](https://github.com/elastic/security-team/issues/1974) epic. Status: `in progress`. @@ -24,6 +24,8 @@ Status: `in progress`. #### Scenario: Importing an unmodified prebuilt rule with a matching rule_id and version +**Automation**: 1 cypress test and 1 integration test. + ```Gherkin Given the import payload contains a prebuilt rule with a matching rule_id and version, identical to the published rule When the user imports the rule @@ -34,26 +36,48 @@ And isCustomized should be false #### Scenario: Importing a customized prebuilt rule with a matching rule_id and version +**Automation**: 1 cypress test and 1 integration test. + ```Gherkin Given the import payload contains a prebuilt rule with a matching rule_id and version, modified from the published version +And the overwrite flag is set to true When the user imports the rule Then the rule should be created or updated And the ruleSource type should be "external" And isCustomized should be true + +CASE: Should work with older, newer, or identical version numbers +``` + +#### Scenario: Importing a custom rule with a matching rule_id and version + +**Automation**: 1 cypress test and 1 integration test. + +```Gherkin +Given the import payload contains a custom rule with a matching rule_id and version +And the overwrite flag is set to true +When the user imports the rule +Then the rule should be updated +And the ruleSource type should be "internal" ``` #### Scenario: Importing a prebuilt rule with a matching rule_id but no matching version +**Automation**: 1 integration test. + ```Gherkin Given the import payload contains a prebuilt rule with a matching rule_id but no matching version +And the overwrite flag is set to true When the user imports the rule -Then the rule should be created or updated +Then the rule should be created And the ruleSource type should be "external" And isCustomized should be true ``` #### Scenario: Importing a prebuilt rule with a non-existent rule_id +**Automation**: 1 integration test. + ```Gherkin Given the import payload contains a prebuilt rule with a non-existent rule_id When the user imports the rule @@ -63,6 +87,8 @@ And the ruleSource type should be "internal" #### Scenario: Importing a prebuilt rule without a rule_id field +**Automation**: 1 integration test. + ```Gherkin Given the import payload contains a prebuilt rule without a rule_id field When the user imports the rule @@ -71,6 +97,8 @@ Then the import should be rejected with a message "rule_id field is required" #### Scenario: Importing a prebuilt rule with a matching rule_id but missing a version field +**Automation**: 1 integration test. + ```Gherkin Given the import payload contains a prebuilt rule without a version field When the user imports the rule @@ -79,6 +107,8 @@ Then the import should be rejected with a message "version field is required" #### Scenario: Importing an existing custom rule missing a version field +**Automation**: 1 integration test. + ```Gherkin Given the import payload contains an existing custom rule without a version field When the user imports the rule @@ -89,6 +119,8 @@ And the "version" field should be set to the existing rule's "version" #### Scenario: Importing a new custom rule missing a version field +**Automation**: 1 integration test. + ```Gherkin Given the import payload contains a new custom rule without a version field When the user imports the rule @@ -99,6 +131,8 @@ And the "version" field should be set to 1 #### Scenario: Importing a rule with overwrite flag set to true +**Automation**: 1 integration test. + ```Gherkin Given the import payload contains a rule with an existing rule_id And the overwrite flag is set to true @@ -109,15 +143,21 @@ And the ruleSource type should be calculated based on the rule_id and version #### Scenario: Importing a rule with overwrite flag set to false +**Automation**: 1 integration test. + ```Gherkin Given the import payload contains a rule with an existing rule_id And the overwrite flag is set to false When the user imports the rule Then the import should be rejected with a message "rule_id already exists" + +CASE: should have the same outcome for all rule types ``` #### Scenario: Importing both custom and prebuilt rules +**Automation**: 1 integration test. + ```Gherkin Given the import payload contains modified and unmodified, custom and prebuilt rules When the user imports the rule @@ -125,3 +165,25 @@ Then custom rules should be created or updated, with versions defaulted to 1 And prebuilt rules should be created or updated, And prebuilt rules missing versions should be rejected ``` + +#### Scenario: Importing prebuilt rules when the rules package is not installed + +**Automation**: 1 integration test. + +```Gherkin +Given the import payload contains prebuilt rules +And no rules package has been installed locally +When the user imports the rule +Then all rules should be created or updated as custom rules +``` + +#### Scenario: User imports a custom rule before a prebuilt rule asset is created with the same rule_id + +**Automation**: 1 integration test. + +```Gherkin +Given the environment contains an imported custom rule +And this rule has a rule_id of X +When a prebuilt rule asset is added with a rule_id of X +Then the imported custom rule should be upgradeable as if it were a prebuilt rule +``` diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/add_to_timeline.test.ts b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/add_to_timeline.test.ts index 3d105c34515b4..f17257bb25b3c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/add_to_timeline.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/add_to_timeline.test.ts @@ -104,6 +104,54 @@ describe('createAddToTimelineCellAction', () => { }) ).toEqual(false); }); + + it('should return true if the user has read access to timeline', async () => { + const factory = createAddToTimelineCellActionFactory({ + store, + services: { + ...services, + application: { + ...services.application, + capabilities: { + ...services.application.capabilities, + securitySolutionTimeline: { + read: true, + }, + }, + }, + }, + }); + const addToTimelineActionIsCompatible = factory({ + id: 'testAddToTimeline', + order: 1, + }); + + expect(await addToTimelineActionIsCompatible.isCompatible(context)).toEqual(true); + }); + + it('should return false if the user does not have access to timeline', async () => { + const factory = createAddToTimelineCellActionFactory({ + store, + services: { + ...services, + application: { + ...services.application, + capabilities: { + ...services.application.capabilities, + securitySolutionTimeline: { + read: false, + }, + }, + }, + }, + }); + const addToTimelineActionIsCompatible = factory({ + id: 'testAddToTimeline', + order: 1, + }); + + expect(await addToTimelineActionIsCompatible.isCompatible(context)).toEqual(false); + }); }); describe('execute', () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/add_to_timeline.ts b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/add_to_timeline.ts index 695569e98ee97..fafd7cc8ed7fc 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/add_to_timeline.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/add_to_timeline.ts @@ -17,6 +17,7 @@ import type { KBN_FIELD_TYPES } from '@kbn/field-types'; import { addProvider } from '../../../../timelines/store/actions'; import { TimelineId } from '../../../../../common/types'; import type { SecurityAppStore } from '../../../../common/store'; +import { extractTimelineCapabilities } from '../../../../common/utils/timeline_capabilities'; import { fieldHasCellActions } from '../../utils'; import { ADD_TO_TIMELINE, @@ -38,17 +39,22 @@ export const createAddToTimelineCellActionFactory = createCellActionFactory( store: SecurityAppStore; services: StartServices; }): CellActionTemplate => { - const { notifications: notificationsService } = services; - + const { + notifications: notificationsService, + application: { capabilities }, + } = services; + const timelineCapabilities = extractTimelineCapabilities(capabilities); return { type: SecurityCellActionType.ADD_TO_TIMELINE, getIconType: () => ADD_TO_TIMELINE_ICON, getDisplayName: () => ADD_TO_TIMELINE, getDisplayNameTooltip: () => ADD_TO_TIMELINE, - isCompatible: async ({ data }) => { + + isCompatible: async ({ data, metadata }) => { const field = data[0]?.field; return ( + timelineCapabilities.read && data.length === 1 && // TODO Add support for multiple values fieldHasCellActions(field.name) && isValidDataProviderField(field.name, field.type) && diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/investigate_in_new_timeline.test.ts b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/investigate_in_new_timeline.test.ts index d7750dd1cd4cd..74f0aff7de934 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/investigate_in_new_timeline.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/investigate_in_new_timeline.test.ts @@ -107,6 +107,52 @@ describe('createAddToNewTimelineCellAction', () => { }) ).toEqual(false); }); + + it('should return true if the the user has read access to timeline', async () => { + const factory = createInvestigateInNewTimelineCellActionFactory({ + store, + services: { + ...services, + application: { + ...services.application, + capabilities: { + ...services.application.capabilities, + securitySolutionTimeline: { + read: true, + }, + }, + }, + }, + }); + const addToTimelineActionIsCompatible = factory({ + id: 'testAddToTimeline', + order: 1, + }); + expect(await addToTimelineActionIsCompatible.isCompatible(context)).toEqual(true); + }); + + it('should return flase if the user does not have access to timeline', async () => { + const factory = createInvestigateInNewTimelineCellActionFactory({ + store, + services: { + ...services, + application: { + ...services.application, + capabilities: { + ...services.application.capabilities, + securitySolutionTimeline: { + read: false, + }, + }, + }, + }, + }); + const addToTimelineActionIsCompatible = factory({ + id: 'testAddToTimeline', + order: 1, + }); + expect(await addToTimelineActionIsCompatible.isCompatible(context)).toEqual(false); + }); }); describe('execute', () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/investigate_in_new_timeline.ts b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/investigate_in_new_timeline.ts index ac0be8ea9eb15..f032843701ccf 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/investigate_in_new_timeline.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/investigate_in_new_timeline.ts @@ -19,6 +19,7 @@ import { addProvider, showTimeline } from '../../../../timelines/store/actions'; import { TimelineId } from '../../../../../common/types'; import type { SecurityAppStore } from '../../../../common/store'; import { fieldHasCellActions } from '../../utils'; +import { extractTimelineCapabilities } from '../../../../common/utils/timeline_capabilities'; import { ADD_TO_TIMELINE_FAILED_TEXT, ADD_TO_TIMELINE_FAILED_TITLE, @@ -39,7 +40,11 @@ export const createInvestigateInNewTimelineCellActionFactory = createCellActionF store: SecurityAppStore; services: StartServices; }): CellActionTemplate => { - const { notifications: notificationsService } = services; + const { + notifications: notificationsService, + application: { capabilities }, + } = services; + const timelineCapabilities = extractTimelineCapabilities(capabilities); return { type: SecurityCellActionType.INVESTIGATE_IN_NEW_TIMELINE, @@ -50,6 +55,7 @@ export const createInvestigateInNewTimelineCellActionFactory = createCellActionF const field = data[0]?.field; return ( + timelineCapabilities.read && data.length === 1 && // TODO Add support for multiple values fieldHasCellActions(field.name) && isValidDataProviderField(field.name, field.type) && diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/discover/add_to_timeline.test.ts b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/discover/add_to_timeline.test.ts index b79017aa322bb..240ef5a191a2a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/discover/add_to_timeline.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/discover/add_to_timeline.test.ts @@ -100,6 +100,54 @@ describe('createAddToTimelineDiscoverCellActionFactory', () => { }) ).toEqual(false); }); + + it('should return true if the user has read access to timeline', async () => { + const factory = createAddToTimelineDiscoverCellActionFactory({ + store, + services: { + ...services, + application: { + ...services.application, + capabilities: { + ...services.application.capabilities, + securitySolutionTimeline: { + read: true, + }, + }, + }, + }, + }); + const addToTimelineActionIsCompatible = factory({ + id: 'testAddToTimeline', + order: 1, + }); + + expect(await addToTimelineActionIsCompatible.isCompatible(context)).toEqual(true); + }); + + it('should return false if the user does not have access to timeline', async () => { + const factory = createAddToTimelineDiscoverCellActionFactory({ + store, + services: { + ...services, + application: { + ...services.application, + capabilities: { + ...services.application.capabilities, + securitySolutionTimeline: { + read: false, + }, + }, + }, + }, + }); + const addToTimelineActionIsCompatible = factory({ + id: 'testAddToTimeline', + order: 1, + }); + + expect(await addToTimelineActionIsCompatible.isCompatible(context)).toEqual(false); + }); }); describe('execute', () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/discover/add_to_timeline.ts b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/discover/add_to_timeline.ts index 27b309b2acee4..0690454151c30 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/discover/add_to_timeline.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/discover/add_to_timeline.ts @@ -8,6 +8,7 @@ import type { CellAction, CellActionFactory } from '@kbn/cell-actions'; import { isInSecurityApp } from '../../../../common/hooks/is_in_security_app'; import type { SecurityAppStore } from '../../../../common/store'; +import { extractTimelineCapabilities } from '../../../../common/utils/timeline_capabilities'; import type { StartServices } from '../../../../types'; import { createAddToTimelineCellActionFactory } from '../cell_action/add_to_timeline'; @@ -19,6 +20,7 @@ export const createAddToTimelineDiscoverCellActionFactory = ({ services: StartServices; }): CellActionFactory => { const { application } = services; + const timelineCapabilities = extractTimelineCapabilities(application.capabilities); let currentAppId: string | undefined; application.currentAppId$.subscribe((appId) => { @@ -31,6 +33,6 @@ export const createAddToTimelineDiscoverCellActionFactory = ({ }); return securityAddToTimelineActionFactory.combine({ - isCompatible: async () => isInSecurityApp(currentAppId), + isCompatible: async () => timelineCapabilities.read && isInSecurityApp(currentAppId), }); }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.test.ts b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.test.ts index 362fb5f9ee885..06437f3851762 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.test.ts @@ -163,8 +163,26 @@ describe('createAddToTimelineLensAction', () => { expect(await addToTimelineAction.isCompatible(context)).toEqual(false); }); - it('should return true if everything is okay', async () => { - expect(await addToTimelineAction.isCompatible(context)).toEqual(true); + it('should return false when the user does not have access to timeline', async () => { + ( + KibanaServices.get().application.capabilities.securitySolutionTimeline as { + crud: boolean; + read: boolean; + } + ).read = false; + const _action = createAddToTimelineLensAction({ store, order: 1 }); + expect(await _action.isCompatible(context)).toEqual(false); + }); + + it('should return true when the user has read access to timeline', async () => { + ( + KibanaServices.get().application.capabilities.securitySolutionTimeline as { + crud: boolean; + read: boolean; + } + ).read = true; + const _action = createAddToTimelineLensAction({ store, order: 1 }); + expect(await _action.isCompatible(context)).toEqual(false); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.ts b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.ts index 2a2b11a9beb15..4849bf5f2d799 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.ts @@ -14,6 +14,7 @@ import { KibanaServices } from '../../../../common/lib/kibana'; import type { SecurityAppStore } from '../../../../common/store/types'; import { addProvider } from '../../../../timelines/store/actions'; import type { DataProvider } from '../../../../../common/types'; +import { extractTimelineCapabilities } from '../../../../common/utils/timeline_capabilities'; import { EXISTS_OPERATOR, TimelineId } from '../../../../../common/types'; import { fieldHasCellActions } from '../../utils'; import { @@ -76,6 +77,7 @@ export const createAddToTimelineLensAction = ({ applicationService.currentAppId$.subscribe((appId) => { currentAppId = appId; }); + const timelineCapabilities = extractTimelineCapabilities(applicationService.capabilities); return createAction({ id: ACTION_ID, @@ -84,6 +86,7 @@ export const createAddToTimelineLensAction = ({ getIconType: () => ADD_TO_TIMELINE_ICON, getDisplayName: () => ADD_TO_TIMELINE, isCompatible: async ({ embeddable, data }) => + timelineCapabilities.read && !hasBlockingError(embeddable) && isLensApi(embeddable) && apiPublishesUnifiedSearch(embeddable) && diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/app_routes.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/app/app_routes.test.tsx index 585323a7b8da9..20fecf03e6863 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/app_routes.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/app/app_routes.test.tsx @@ -14,7 +14,7 @@ import { noCasesCapabilities, readCasesCapabilities, } from '../cases_test_utils'; -import { CASES_FEATURE_ID, SERVER_APP_ID } from '../../common/constants'; +import { CASES_FEATURE_ID, SECURITY_FEATURE_ID } from '../../common/constants'; const mockNotFoundPage = jest.fn(() => null); jest.mock('./404', () => ({ @@ -33,7 +33,7 @@ describe('RedirectRoute', () => { it('RedirectRoute should redirect to overview page when siem and case privileges are all', () => { const mockCapabilities = { - [SERVER_APP_ID]: { show: true, crud: true }, + [SECURITY_FEATURE_ID]: { show: true, crud: true }, [CASES_FEATURE_ID]: allCasesCapabilities(), } as unknown as Capabilities; render(); @@ -42,7 +42,7 @@ describe('RedirectRoute', () => { it('RedirectRoute should redirect to overview page when siem and case privileges are read', () => { const mockCapabilities = { - [SERVER_APP_ID]: { show: true, crud: false }, + [SECURITY_FEATURE_ID]: { show: true, crud: false }, [CASES_FEATURE_ID]: readCasesCapabilities(), } as unknown as Capabilities; render(); @@ -51,7 +51,7 @@ describe('RedirectRoute', () => { it('RedirectRoute should redirect to not_found page when siem and case privileges are off', () => { const mockCapabilities = { - [SERVER_APP_ID]: { show: false, crud: false }, + [SECURITY_FEATURE_ID]: { show: false, crud: false }, [CASES_FEATURE_ID]: noCasesCapabilities(), } as unknown as Capabilities; render(); @@ -61,7 +61,7 @@ describe('RedirectRoute', () => { it('RedirectRoute should redirect to overview page when siem privilege is read and case privilege is all', () => { const mockCapabilities = { - [SERVER_APP_ID]: { show: true, crud: false }, + [SECURITY_FEATURE_ID]: { show: true, crud: false }, [CASES_FEATURE_ID]: allCasesCapabilities(), } as unknown as Capabilities; render(); @@ -70,7 +70,7 @@ describe('RedirectRoute', () => { it('RedirectRoute should redirect to overview page when siem privilege is read and case privilege is read', () => { const mockCapabilities = { - [SERVER_APP_ID]: { show: true, crud: false }, + [SECURITY_FEATURE_ID]: { show: true, crud: false }, [CASES_FEATURE_ID]: allCasesCapabilities(), } as unknown as Capabilities; render(); @@ -79,7 +79,7 @@ describe('RedirectRoute', () => { it('RedirectRoute should redirect to cases page when siem privilege is none and case privilege is read', () => { const mockCapabilities = { - [SERVER_APP_ID]: { show: false, crud: false }, + [SECURITY_FEATURE_ID]: { show: false, crud: false }, [CASES_FEATURE_ID]: readCasesCapabilities(), } as unknown as Capabilities; render(); @@ -88,7 +88,7 @@ describe('RedirectRoute', () => { it('RedirectRoute should redirect to cases page when siem privilege is none and case privilege is all', () => { const mockCapabilities = { - [SERVER_APP_ID]: { show: false, crud: false }, + [SECURITY_FEATURE_ID]: { show: false, crud: false }, [CASES_FEATURE_ID]: allCasesCapabilities(), } as unknown as Capabilities; render(); diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/app_routes.tsx b/x-pack/solutions/security/plugins/security_solution/public/app/app_routes.tsx index 4b3913bfb4d3c..86423642b4091 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/app_routes.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/app/app_routes.tsx @@ -10,14 +10,10 @@ import type { RouteProps } from 'react-router-dom'; import { Redirect } from 'react-router-dom'; import { Routes, Route } from '@kbn/shared-ux-router'; import type { Capabilities } from '@kbn/core/public'; -import { - CASES_FEATURE_ID, - CASES_PATH, - ONBOARDING_PATH, - SERVER_APP_ID, -} from '../../common/constants'; +import { CASES_FEATURE_ID, CASES_PATH, ONBOARDING_PATH } from '../../common/constants'; import { NotFoundPage } from './404'; import type { StartServices } from '../types'; +import { hasAccessToSecuritySolution } from '../helpers_access'; export interface AppRoutesProps { services: StartServices; @@ -37,7 +33,7 @@ export const AppRoutes: React.FC = React.memo(({ services, subPl AppRoutes.displayName = 'AppRoutes'; export const RedirectRoute = React.memo<{ capabilities: Capabilities }>(({ capabilities }) => { - if (capabilities[SERVER_APP_ID].show === true) { + if (hasAccessToSecuritySolution(capabilities)) { return ; } if (capabilities[CASES_FEATURE_ID].read_cases === true) { diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/assets_links.ts b/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/assets_links.ts index c77e0fe7a03e7..b6bb88d7dd321 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/assets_links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/assets_links.ts @@ -7,7 +7,7 @@ import { SecurityPageName, ExternalPageName } from '@kbn/security-solution-navigation'; import { ASSETS_PATH, CLOUD_DEFEND_PATH } from '../../../../../common/constants'; -import { SERVER_APP_ID } from '../../../../../common'; +import { SECURITY_FEATURE_ID } from '../../../../../common'; import type { LinkItem } from '../../../../common/links/types'; import type { SolutionNavLink } from '../../../../common/links'; import { IconEcctlLazy, IconFleetLazy } from './lazy_icons'; @@ -18,7 +18,7 @@ const assetsAppLink: LinkItem = { id: SecurityPageName.assets, title: i18n.ASSETS_TITLE, path: ASSETS_PATH, - capabilities: [`${SERVER_APP_ID}.show`], + capabilities: [`${SECURITY_FEATURE_ID}.show`], hideTimeline: true, skipUrlState: true, links: [], // endpoints and cloudDefend links are added in createAssetsLinkFromManage @@ -30,7 +30,7 @@ const assetsCloudDefendAppLink: LinkItem = { title: i18n.CLOUD_DEFEND_TITLE, description: i18n.CLOUD_DEFEND_DESCRIPTION, path: CLOUD_DEFEND_PATH, - capabilities: [`${SERVER_APP_ID}.show`], + capabilities: [`${SECURITY_FEATURE_ID}.show`], landingIcon: IconEcctlLazy, isBeta: true, hideTimeline: true, diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/investigations_links.ts b/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/investigations_links.ts index ddcd88667d967..de41c8f74d6fa 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/investigations_links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/investigations_links.ts @@ -7,7 +7,7 @@ import { ExternalPageName, SecurityPageName } from '@kbn/security-solution-navigation'; import { INVESTIGATIONS_PATH } from '../../../../../common/constants'; -import { SERVER_APP_ID } from '../../../../../common'; +import { SECURITY_FEATURE_ID } from '../../../../../common'; import type { LinkItem } from '../../../../common/links/types'; import type { SolutionNavLink } from '../../../../common/links'; import { IconOsqueryLazy, IconTimelineLazy } from './lazy_icons'; @@ -18,7 +18,7 @@ const investigationsAppLink: LinkItem = { id: SecurityPageName.investigations, title: i18n.INVESTIGATIONS_TITLE, path: INVESTIGATIONS_PATH, - capabilities: [`${SERVER_APP_ID}.show`], + capabilities: [`${SECURITY_FEATURE_ID}.show`], hideTimeline: true, skipUrlState: true, links: [], // timeline and note links are added via the methods below diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/ml_links.ts b/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/ml_links.ts index f9ef049c73d30..e1e44d0e9195d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/ml_links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/ml_links.ts @@ -12,7 +12,7 @@ import { } from '@kbn/security-solution-navigation'; import { MACHINE_LEARNING_PATH } from '../../../../../common/constants'; import type { LinkItem } from '../../../../common/links/types'; -import { SERVER_APP_ID } from '../../../../../common'; +import { SECURITY_FEATURE_ID } from '../../../../../common'; import type { SolutionLinkCategory, SolutionNavLink } from '../../../../common/links'; import { IconLensLazy, @@ -39,7 +39,7 @@ export const mlAppLink: LinkItem = { id: SecurityPageName.mlLanding, title: i18n.ML_TITLE, path: MACHINE_LEARNING_PATH, - capabilities: [[`${SERVER_APP_ID}.show`, `ml.canGetJobs`]], + capabilities: [[`${SECURITY_FEATURE_ID}.show`, `ml.canGetJobs`]], globalSearchKeywords: [i18n.ML_KEYWORD], hideTimeline: true, skipUrlState: true, diff --git a/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/components/search_bar.tsx b/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/components/search_bar.tsx new file mode 100644 index 0000000000000..7e9409035ce66 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/components/search_bar.tsx @@ -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 React from 'react'; +import { css } from '@emotion/react'; +import { type EuiThemeComputed, useEuiTheme } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import type { Filter } from '@kbn/es-query'; +import { useKibana } from '../../common/lib/kibana'; +import { FiltersGlobal } from '../../common/components/filters_global/filters_global'; +import { useDataViewContext } from '../hooks/data_view_context'; +import type { AssetsBaseURLQuery } from '../hooks/use_asset_inventory_data_table'; + +type SearchBarQueryProps = Pick; + +interface AssetInventorySearchBarProps { + setQuery(v: Partial): void; + loading: boolean; + placeholder?: string; + query: SearchBarQueryProps; +} + +export const AssetInventorySearchBar = ({ + loading, + query, + setQuery, + placeholder = i18n.translate( + 'xpack.securitySolution.assetInventory.searchBar.searchPlaceholder', + { + defaultMessage: 'Filter your data using KQL syntax', + } + ), +}: AssetInventorySearchBarProps) => { + const { euiTheme } = useEuiTheme(); + const { + unifiedSearch: { + ui: { SearchBar }, + }, + } = useKibana().services; + + const { dataView } = useDataViewContext(); + + return ( + +
+ setQuery({ filters: value })} + placeholder={placeholder} + query={{ + query: query?.query?.query || '', + language: query?.query?.language || 'kuery', + }} + filters={query?.filters || []} + /> +
+
+ ); +}; + +const getContainerStyle = (theme: EuiThemeComputed) => css` + border-bottom: ${theme.border.thin}; + background-color: ${theme.colors.body}; + padding: ${theme.size.base}; +`; diff --git a/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/pages/all_assets.tsx b/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/pages/all_assets.tsx index 128c82a266bac..5269d634cd8dd 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/pages/all_assets.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/pages/all_assets.tsx @@ -42,6 +42,7 @@ import { useKibana } from '../../common/lib/kibana'; import { AssetCriticalityBadge } from '../../entity_analytics/components/asset_criticality/asset_criticality_badge'; import { EmptyState } from '../components/empty_state'; import { AdditionalControls } from '../components/additional_controls'; +import { AssetInventorySearchBar } from '../components/search_bar'; import { useDataViewContext } from '../hooks/data_view_context'; import { useStyles } from '../hooks/use_styles'; @@ -366,6 +367,11 @@ const AllAssets = ({ return ( +

diff --git a/x-pack/solutions/security/plugins/security_solution/public/assistant/send_to_timeline/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/assistant/send_to_timeline/index.tsx index 86d9cf727be77..470e773003a67 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/assistant/send_to_timeline/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/assistant/send_to_timeline/index.tsx @@ -12,6 +12,7 @@ import type { Filter } from '@kbn/es-query'; import { useDispatch, useSelector } from 'react-redux'; import { useAssistantContext } from '@kbn/elastic-assistant'; +import { extractTimelineCapabilities } from '../../common/utils/timeline_capabilities'; import { sourcererSelectors } from '../../common/store'; import { sourcererActions } from '../../common/store/actions'; import { inputsActions } from '../../common/store/inputs'; @@ -36,6 +37,7 @@ import { useDiscoverInTimelineContext } from '../../common/components/discover_i import { useShowTimeline } from '../../common/utils/timeline/use_show_timeline'; import { useSourcererDataView } from '../../sourcerer/containers'; import { useDiscoverState } from '../../timelines/components/timeline/tabs/esql/use_discover_state'; +import { useKibana } from '../../common/lib/kibana'; export interface SendToTimelineButtonProps { asEmptyButton: boolean; @@ -61,7 +63,10 @@ export const SendToTimelineButton: FC { it('for serverless, it specifies capabilities as an AND condition, via a nested array', () => { expect(links.capabilities).toEqual([ - [`${SERVER_APP_ID}.show`, `${ATTACK_DISCOVERY_FEATURE_ID}.attack-discovery`], + [`${SECURITY_FEATURE_ID}.show`, `${ATTACK_DISCOVERY_FEATURE_ID}.attack-discovery`], ]); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/links.ts b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/links.ts index 531c0a1c48610..bab8fec37b6de 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/links.ts @@ -12,12 +12,14 @@ import { ATTACK_DISCOVERY_FEATURE_ID, ATTACK_DISCOVERY_PATH, SecurityPageName, - SERVER_APP_ID, + SECURITY_FEATURE_ID, } from '../../common/constants'; import type { LinkItem } from '../common/links/types'; export const links: LinkItem = { - capabilities: [[`${SERVER_APP_ID}.show`, `${ATTACK_DISCOVERY_FEATURE_ID}.attack-discovery`]], // This is an AND condition via the nested array + capabilities: [ + [`${SECURITY_FEATURE_ID}.show`, `${ATTACK_DISCOVERY_FEATURE_ID}.attack-discovery`], + ], // This is an AND condition via the nested array globalNavPosition: 4, globalSearchKeywords: [ i18n.translate('xpack.securitySolution.appLinks.attackDiscovery', { diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/index.test.tsx index fe59d4cda04cd..1445a5d1ba3cd 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/index.test.tsx @@ -66,7 +66,7 @@ jest.mock( jest.mock('../../common/links', () => ({ useLinkInfo: jest.fn().mockReturnValue({ - capabilities: ['siem.show'], + capabilities: ['siemV2.show'], globalNavPosition: 4, globalSearchKeywords: ['Attack discovery'], id: 'attack_discovery', @@ -117,7 +117,7 @@ jest.mock('../../common/lib/kibana', () => { services: { application: { capabilities: { - siem: { crud_alerts: true, read_alerts: true }, + siemV2: { crud_alerts: true, read_alerts: true }, }, navigateToUrl: jest.fn(), }, @@ -149,7 +149,7 @@ jest.mock('../../common/lib/kibana', () => { dataViews: mockDataViewsService, docLinks: { links: { - siem: { + siemV2: { privileges: 'link', }, }, diff --git a/x-pack/solutions/security/plugins/security_solution/public/cases/pages/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/cases/pages/index.tsx index 787dfc973c5d2..bc90dfcd0dc02 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/cases/pages/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/cases/pages/index.tsx @@ -21,6 +21,7 @@ import { SecuritySolutionPageWrapper } from '../../common/components/page_wrappe import { getEndpointDetailsPath } from '../../management/common/routing'; import { SpyRoute } from '../../common/utils/route/spy_routes'; import { useInsertTimeline } from '../components/use_insert_timeline'; +import { useUserPrivileges } from '../../common/components/user_privileges'; import * as timelineMarkdownPlugin from '../../common/components/markdown_editor/plugins/timeline'; import { useFetchAlertData } from './use_fetch_alert_data'; import { useUpsellingMessage } from '../../common/hooks/use_upselling'; @@ -33,6 +34,9 @@ const CaseContainerComponent: React.FC = () => { const userCasesPermissions = cases.helpers.canUseCases([APP_ID]); const dispatch = useDispatch(); const { openFlyout } = useExpandableFlyoutApi(); + const { + timelinePrivileges: { read: canSeeTimeline }, + } = useUserPrivileges(); const interactionsUpsellingMessage = useUpsellingMessage('investigation_guide_interactions'); @@ -129,7 +133,10 @@ const CaseContainerComponent: React.FC = () => { editor_plugins: { parsingPlugin: timelineMarkdownPlugin.parser, processingPluginRenderer: timelineMarkdownPlugin.renderer, - uiPlugin: timelineMarkdownPlugin.plugin({ interactionsUpsellingMessage }), + uiPlugin: timelineMarkdownPlugin.plugin({ + interactionsUpsellingMessage, + canSeeTimeline, + }), }, hooks: { useInsertTimeline, diff --git a/x-pack/solutions/security/plugins/security_solution/public/cloud_defend/links.ts b/x-pack/solutions/security/plugins/security_solution/public/cloud_defend/links.ts index c1748664a966d..cbc0a710a7ba1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/cloud_defend/links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/cloud_defend/links.ts @@ -7,13 +7,13 @@ import { getSecuritySolutionLink } from '@kbn/cloud-defend-plugin/public'; import { i18n } from '@kbn/i18n'; import type { SecurityPageName } from '../../common/constants'; -import { SERVER_APP_ID } from '../../common/constants'; +import { SECURITY_FEATURE_ID } from '../../common/constants'; import type { LinkItem } from '../common/links/types'; import { IconCloudDefend } from '../common/icons/cloud_defend'; const commonLinkProperties: Partial = { hideTimeline: true, - capabilities: [`${SERVER_APP_ID}.show`], + capabilities: [`${SECURITY_FEATURE_ID}.show`], }; export const cloudDefendLink: LinkItem = { diff --git a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/alerts/alerts_preview.tsx b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/alerts/alerts_preview.tsx index cd5fcc93495a1..d9d85db0d4a09 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/alerts/alerts_preview.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/alerts/alerts_preview.tsx @@ -6,6 +6,7 @@ */ import React, { useCallback, useMemo } from 'react'; +import { css } from '@emotion/react'; import { capitalize } from 'lodash'; import type { EuiThemeComputed } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, EuiTitle, useEuiTheme } from '@elastic/eui'; @@ -36,17 +37,17 @@ const AlertsCount = ({ -

+

{getAbbreviatedNumber(alertsTotal)} -

+

{ + ({ field, value }: { field: CloudPostureEntityIdentifier; value: string }) => { useEffect(() => { uiMetricService.trackUiMetric( METRIC_TYPE.COUNT, diff --git a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/csp_details/insights_tab_csp.tsx b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/csp_details/insights_tab_csp.tsx index 84e3ee4faee99..ac50d22bbb833 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/csp_details/insights_tab_csp.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/csp_details/insights_tab_csp.tsx @@ -16,6 +16,7 @@ import { CspInsightLeftPanelSubTab } from '../../../flyout/entity_details/shared import { MisconfigurationFindingsDetailsTable } from './misconfiguration_findings_details_table'; import { VulnerabilitiesFindingsDetailsTable } from './vulnerabilities_findings_details_table'; import { AlertsDetailsTable } from './alerts_findings_details_table'; +import type { CloudPostureEntityIdentifier } from '../entity_insight'; /** * Insights view displayed in the document details expandable flyout left section @@ -42,7 +43,7 @@ function isCspFlyoutPanelProps( } export const InsightsTabCsp = memo( - ({ value, field }: { value: string; field: 'host.name' | 'user.name' }) => { + ({ value, field }: { value: string; field: CloudPostureEntityIdentifier }) => { const panels = useExpandableFlyoutState(); let hasMisconfigurationFindings = false; diff --git a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/csp_details/misconfiguration_findings_details_table.tsx b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/csp_details/misconfiguration_findings_details_table.tsx index c03f7585cfc72..68dbe72449ba3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/csp_details/misconfiguration_findings_details_table.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/csp_details/misconfiguration_findings_details_table.tsx @@ -19,10 +19,10 @@ import { MISCONFIGURATION_STATUS, buildMisconfigurationEntityFlyoutPreviewQuery, } from '@kbn/cloud-security-posture-common'; -import { euiThemeVars } from '@kbn/ui-theme'; import { DistributionBar } from '@kbn/security-solution-distribution-bar'; import type { CspBenchmarkRuleMetadata } from '@kbn/cloud-security-posture-common/schema/rules/latest'; -import { CspEvaluationBadge } from '@kbn/cloud-security-posture'; +import { CspEvaluationBadge, getMisconfigurationStatusColor } from '@kbn/cloud-security-posture'; + import { ENTITY_FLYOUT_EXPAND_MISCONFIGURATION_VIEW_VISITS, NAV_TO_FINDINGS_BY_HOST_NAME_FRPOM_ENTITY_FLYOUT, @@ -34,6 +34,7 @@ import { useGetNavigationUrlParams } from '@kbn/cloud-security-posture/src/hooks import { SecurityPageName } from '@kbn/deeplinks-security'; import { useHasMisconfigurations } from '@kbn/cloud-security-posture/src/hooks/use_has_misconfigurations'; import { SecuritySolutionLinkAnchor } from '../../../common/components/links'; +import type { CloudPostureEntityIdentifier } from '../entity_insight'; type MisconfigurationSortFieldType = | MISCONFIGURATION.RESULT_EVALUATION @@ -57,7 +58,7 @@ const getFindingsStats = ( } ), count: passedFindingsStats, - color: euiThemeVars.euiColorSuccess, + color: getMisconfigurationStatusColor(MISCONFIGURATION_STATUS.PASSED), filter: () => { filterFunction(MISCONFIGURATION_STATUS.PASSED); }, @@ -75,7 +76,7 @@ const getFindingsStats = ( } ), count: failedFindingsStats, - color: euiThemeVars.euiColorVis9, + color: getMisconfigurationStatusColor(MISCONFIGURATION_STATUS.FAILED), filter: () => { filterFunction(MISCONFIGURATION_STATUS.FAILED); }, @@ -92,7 +93,7 @@ const getFindingsStats = ( * Insights view displayed in the document details expandable flyout left section */ export const MisconfigurationFindingsDetailsTable = memo( - ({ field, value }: { field: 'host.name' | 'user.name'; value: string }) => { + ({ field, value }: { field: CloudPostureEntityIdentifier; value: string }) => { useEffect(() => { uiMetricService.trackUiMetric( METRIC_TYPE.COUNT, @@ -178,14 +179,14 @@ export const MisconfigurationFindingsDetailsTable = memo( return getNavUrlParams({ 'rule.id': ruleId, 'resource.id': resourceId }, 'configurations'); }; - const getFindingsPageUrl = (name: string, queryField: 'host.name' | 'user.name') => { + const getFindingsPageUrl = (name: string, queryField: CloudPostureEntityIdentifier) => { return getNavUrlParams({ [queryField]: name }, 'configurations', ['rule.name']); }; const linkWidth = 40; const resultWidth = 74; - const misconfgurationStats = getFindingsStats( + const misconfigurationStats = getFindingsStats( passedFindings, failedFindings, setCurrentFilter, @@ -271,7 +272,7 @@ export const MisconfigurationFindingsDetailsTable = memo( - + { + const { getSeverityStatusColor } = useGetSeverityStatusColor(); + useEffect(() => { uiMetricService.trackUiMetric( METRIC_TYPE.COUNT, @@ -123,7 +128,7 @@ export const VulnerabilitiesFindingsDetailsTable = memo(({ value }: { value: str const getNavUrlParams = useGetNavigationUrlParams(); - const getVulnerabilityUrl = (name: string, queryField: 'host.name' | 'user.name') => { + const getVulnerabilityUrl = (name: string, queryField: CloudPostureEntityIdentifier) => { return getNavUrlParams({ [queryField]: name }, 'vulnerabilities'); }; @@ -152,6 +157,7 @@ export const VulnerabilitiesFindingsDetailsTable = memo(({ value }: { value: str low, none, }, + getSeverityStatusColor, setCurrentFilter, currentFilter ); @@ -237,7 +243,7 @@ export const VulnerabilitiesFindingsDetailsTable = memo(({ value }: { value: str { diff --git a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/entity_insight.tsx b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/entity_insight.tsx index 5479ff069c7c1..6e591945d0725 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/entity_insight.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/entity_insight.tsx @@ -12,6 +12,7 @@ import { css } from '@emotion/react'; import { FormattedMessage } from '@kbn/i18n-react'; import { useHasVulnerabilities } from '@kbn/cloud-security-posture/src/hooks/use_has_vulnerabilities'; import { useHasMisconfigurations } from '@kbn/cloud-security-posture/src/hooks/use_has_misconfigurations'; +import type { EntityIdentifierFields } from '../../../common/entity_analytics/types'; import { MisconfigurationsPreview } from './misconfiguration/misconfiguration_preview'; import { VulnerabilitiesPreview } from './vulnerabilities/vulnerabilities_preview'; import { AlertsPreview } from './alerts/alerts_preview'; @@ -20,6 +21,11 @@ import { DETECTION_RESPONSE_ALERTS_BY_STATUS_ID } from '../../overview/component import { useNonClosedAlerts } from '../hooks/use_non_closed_alerts'; import type { EntityDetailsPath } from '../../flyout/entity_details/shared/components/left_panel/left_panel_header'; +export type CloudPostureEntityIdentifier = Extract< + EntityIdentifierFields, + EntityIdentifierFields.hostName | EntityIdentifierFields.userName +>; + export const EntityInsight = ({ value, field, @@ -28,7 +34,7 @@ export const EntityInsight = ({ openDetailsPanel, }: { value: string; - field: 'host.name' | 'user.name'; + field: CloudPostureEntityIdentifier; isPreviewMode?: boolean; isLinkEnabled: boolean; openDetailsPanel: (path: EntityDetailsPath) => void; diff --git a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/misconfiguration/misconfiguration_preview.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/misconfiguration/misconfiguration_preview.test.tsx index 2d79ecdb2783f..f3d6bb20e2459 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/misconfiguration/misconfiguration_preview.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/misconfiguration/misconfiguration_preview.test.tsx @@ -11,6 +11,7 @@ import { MisconfigurationsPreview } from './misconfiguration_preview'; import { useMisconfigurationPreview } from '@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview'; import { useVulnerabilitiesPreview } from '@kbn/cloud-security-posture/src/hooks/use_vulnerabilities_preview'; import { TestProviders } from '../../../common/mock/test_providers'; +import { EntityIdentifierFields } from '../../../../common/entity_analytics/types'; // Mock hooks jest.mock('@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview'); @@ -33,7 +34,7 @@ describe('MisconfigurationsPreview', () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/misconfiguration/misconfiguration_preview.tsx b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/misconfiguration/misconfiguration_preview.tsx index 2db803fbcda3a..303443c5ef73c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/misconfiguration/misconfiguration_preview.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/misconfiguration/misconfiguration_preview.tsx @@ -7,13 +7,13 @@ import React, { useCallback, useEffect, useMemo } from 'react'; import { css } from '@emotion/react'; -import type { EuiThemeComputed } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, useEuiTheme, EuiTitle } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { DistributionBar } from '@kbn/security-solution-distribution-bar'; import { useHasMisconfigurations } from '@kbn/cloud-security-posture/src/hooks/use_has_misconfigurations'; import { i18n } from '@kbn/i18n'; -import { statusColors } from '@kbn/cloud-security-posture'; +import { getMisconfigurationStatusColor } from '@kbn/cloud-security-posture'; +import { MISCONFIGURATION_STATUS } from '@kbn/cloud-security-posture-common'; import { METRIC_TYPE } from '@kbn/analytics'; import { ENTITY_FLYOUT_WITH_MISCONFIGURATION_VISIT, @@ -25,6 +25,7 @@ import { CspInsightLeftPanelSubTab, EntityDetailsLeftPanelTab, } from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header'; +import type { CloudPostureEntityIdentifier } from '../entity_insight'; export const getFindingsStats = (passedFindingsStats: number, failedFindingsStats: number) => { if (passedFindingsStats === 0 && failedFindingsStats === 0) return []; @@ -37,7 +38,7 @@ export const getFindingsStats = (passedFindingsStats: number, failedFindingsStat } ), count: passedFindingsStats, - color: statusColors.passed, + color: getMisconfigurationStatusColor(MISCONFIGURATION_STATUS.PASSED), }, { key: i18n.translate( @@ -47,7 +48,7 @@ export const getFindingsStats = (passedFindingsStats: number, failedFindingsStat } ), count: failedFindingsStats, - color: statusColors.failed, + color: getMisconfigurationStatusColor(MISCONFIGURATION_STATUS.FAILED), }, ]; }; @@ -55,12 +56,12 @@ export const getFindingsStats = (passedFindingsStats: number, failedFindingsStat const MisconfigurationPreviewScore = ({ passedFindings, failedFindings, - euiTheme, }: { passedFindings: number; failedFindings: number; - euiTheme: EuiThemeComputed<{}>; }) => { + const { euiTheme } = useEuiTheme(); + return ( @@ -95,7 +96,7 @@ export const MisconfigurationsPreview = ({ openDetailsPanel, }: { value: string; - field: 'host.name' | 'user.name'; + field: CloudPostureEntityIdentifier; isPreviewMode?: boolean; isLinkEnabled: boolean; openDetailsPanel: (path: EntityDetailsPath) => void; @@ -157,7 +158,6 @@ export const MisconfigurationsPreview = ({ diff --git a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/vulnerabilities/vulnerabilities_preview.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/vulnerabilities/vulnerabilities_preview.test.tsx index 0fd15b2639280..c4af00ed89cda 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/vulnerabilities/vulnerabilities_preview.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/vulnerabilities/vulnerabilities_preview.test.tsx @@ -11,6 +11,7 @@ import { VulnerabilitiesPreview } from './vulnerabilities_preview'; import { useMisconfigurationPreview } from '@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview'; import { useVulnerabilitiesPreview } from '@kbn/cloud-security-posture/src/hooks/use_vulnerabilities_preview'; import { TestProviders } from '../../../common/mock/test_providers'; +import { EntityIdentifierFields } from '../../../../common/entity_analytics/types'; // Mock hooks jest.mock('@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview'); @@ -33,7 +34,7 @@ describe('VulnerabilitiesPreview', () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/vulnerabilities/vulnerabilities_preview.tsx b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/vulnerabilities/vulnerabilities_preview.tsx index eb5f022eecc95..e1b54ba31da79 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/vulnerabilities/vulnerabilities_preview.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/vulnerabilities/vulnerabilities_preview.tsx @@ -7,11 +7,11 @@ import React, { useCallback, useEffect, useMemo } from 'react'; import { css } from '@emotion/react'; -import type { EuiThemeComputed } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, useEuiTheme, EuiTitle } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { DistributionBar } from '@kbn/security-solution-distribution-bar'; import { useVulnerabilitiesPreview } from '@kbn/cloud-security-posture/src/hooks/use_vulnerabilities_preview'; +import { useGetSeverityStatusColor } from '@kbn/cloud-security-posture/src/hooks/use_get_severity_status_color'; import { buildGenericEntityFlyoutPreviewQuery, getAbbreviatedNumber, @@ -28,14 +28,15 @@ import { CspInsightLeftPanelSubTab, EntityDetailsLeftPanelTab, } from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header'; +import type { CloudPostureEntityIdentifier } from '../entity_insight'; const VulnerabilitiesCount = ({ vulnerabilitiesTotal, - euiTheme, }: { vulnerabilitiesTotal: string | number; - euiTheme: EuiThemeComputed<{}>; }) => { + const { euiTheme } = useEuiTheme(); + return ( @@ -70,7 +71,7 @@ export const VulnerabilitiesPreview = ({ openDetailsPanel, }: { value: string; - field: 'host.name' | 'user.name'; + field: CloudPostureEntityIdentifier; isPreviewMode?: boolean; isLinkEnabled: boolean; openDetailsPanel: (path: EntityDetailsPath) => void; @@ -99,6 +100,7 @@ export const VulnerabilitiesPreview = ({ }); const { euiTheme } = useEuiTheme(); + const { getSeverityStatusColor } = useGetSeverityStatusColor(); const goToEntityInsightTab = useCallback(() => { openDetailsPanel({ @@ -122,6 +124,18 @@ export const VulnerabilitiesPreview = ({ : undefined, [isLinkEnabled, goToEntityInsightTab] ); + + const vulnerabilityStats = getVulnerabilityStats( + { + critical: CRITICAL, + high: HIGH, + medium: MEDIUM, + low: LOW, + none: NONE, + }, + getSeverityStatusColor + ); + return ( - + - + diff --git a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/hooks/use_entity_insight.ts b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/hooks/use_entity_insight.ts index fc35474ffdef0..026bcaea185ec 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/hooks/use_entity_insight.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/hooks/use_entity_insight.ts @@ -16,6 +16,7 @@ import { useGlobalTime } from '../../common/containers/use_global_time'; import { DETECTION_RESPONSE_ALERTS_BY_STATUS_ID } from '../../overview/components/detection_response/alerts_by_status/types'; import { useNonClosedAlerts } from './use_non_closed_alerts'; import { useHasRiskScore } from './use_risk_score_data'; +import type { CloudPostureEntityIdentifier } from '../components/entity_insight'; export const useNavigateEntityInsight = ({ field, @@ -23,7 +24,7 @@ export const useNavigateEntityInsight = ({ subTab, queryIdExtension, }: { - field: 'host.name' | 'user.name'; + field: CloudPostureEntityIdentifier; value: string; subTab: string; queryIdExtension: string; diff --git a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/hooks/use_non_closed_alerts.ts b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/hooks/use_non_closed_alerts.ts index 598f78cd68402..d27dc29091eed 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/hooks/use_non_closed_alerts.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/hooks/use_non_closed_alerts.ts @@ -10,6 +10,7 @@ import { FILTER_CLOSED } from '@kbn/securitysolution-data-table/common/types'; import { useSignalIndex } from '../../detections/containers/detection_engine/alerts/use_signal_index'; import { useAlertsByStatus } from '../../overview/components/detection_response/alerts_by_status/use_alerts_by_status'; import type { ParsedAlertsData } from '../../overview/components/detection_response/alerts_by_status/types'; +import type { CloudPostureEntityIdentifier } from '../components/entity_insight'; export const useNonClosedAlerts = ({ field, @@ -18,7 +19,7 @@ export const useNonClosedAlerts = ({ from, queryId, }: { - field: 'host.name' | 'user.name'; + field: CloudPostureEntityIdentifier; value: string; to: string; from: string; diff --git a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/hooks/use_risk_score_data.ts b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/hooks/use_risk_score_data.ts index 338829d67b0c9..4cd8059a3015a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/hooks/use_risk_score_data.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/hooks/use_risk_score_data.ts @@ -15,12 +15,13 @@ import { import { useRiskScore } from '../../entity_analytics/api/hooks/use_risk_score'; import { FIRST_RECORD_PAGINATION } from '../../entity_analytics/common'; import { EntityType } from '../../../common/entity_analytics/types'; +import type { CloudPostureEntityIdentifier } from '../components/entity_insight'; export const useHasRiskScore = ({ field, value, }: { - field: 'host.name' | 'user.name'; + field: CloudPostureEntityIdentifier; value: string; }) => { const isHostNameField = field === 'host.name'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/links.ts b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/links.ts index e0a66b54f91c0..d22284258680d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/links.ts @@ -7,7 +7,7 @@ import { getSecuritySolutionLink } from '@kbn/cloud-security-posture-plugin/public'; import { i18n } from '@kbn/i18n'; import type { SecurityPageName } from '../../common/constants'; -import { SERVER_APP_ID } from '../../common/constants'; +import { SECURITY_FEATURE_ID } from '../../common/constants'; import cloudSecurityPostureDashboardImage from '../common/images/cloud_security_posture_dashboard_page.png'; import cloudNativeVulnerabilityManagementDashboardImage from '../common/images/cloud_native_vulnerability_management_dashboard_page.png'; import type { LinkItem } from '../common/links/types'; @@ -15,7 +15,7 @@ import { IconEndpoints } from '../common/icons/endpoints'; const commonLinkProperties: Partial = { hideTimeline: true, - capabilities: [`${SERVER_APP_ID}.show`], + capabilities: [`${SECURITY_FEATURE_ID}.show`], }; export const findingsLinks: LinkItem = { diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/control_columns/row_action/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/control_columns/row_action/index.test.tsx index 17039cd443888..37c24472db351 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/control_columns/row_action/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/control_columns/row_action/index.test.tsx @@ -19,6 +19,8 @@ import { DocumentDetailsRightPanelKey } from '../../../../flyout/document_detail import type { ExpandableFlyoutState } from '@kbn/expandable-flyout'; import { useExpandableFlyoutApi, useExpandableFlyoutState } from '@kbn/expandable-flyout'; import { createExpandableFlyoutApiMock } from '../../../mock/expandable_flyout'; +import { useUserPrivileges } from '../../user_privileges'; +import { initialUserPrivilegesState } from '../../user_privileges/user_privileges_context'; const mockDispatch = jest.fn(); jest.mock('react-redux', () => { @@ -57,6 +59,8 @@ jest.mock('@kbn/kibana-react-plugin/public', () => { }); jest.mock('../../guided_onboarding_tour/tour_step'); +jest.mock('../../user_privileges'); + const mockRouteSpy: RouteSpyState = { pageName: SecurityPageName.overview, detailName: undefined, @@ -140,4 +144,40 @@ describe('RowAction', () => { }, }); }); + + describe('privileges', () => { + test('should show notes and timeline buttons when the user has the required privileges', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + ...initialUserPrivilegesState(), + notesPrivileges: { read: true }, + timelinePrivileges: { read: true }, + }); + + const wrapper = render( + + + + ); + + expect(wrapper.queryByTestId('timeline-notes-button-small')).toBeInTheDocument(); + expect(wrapper.queryByTestId('send-alert-to-timeline-button')).toBeInTheDocument(); + }); + + test('should not show notes and timeline buttons when the user does not have the required privileges', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + ...initialUserPrivilegesState(), + notesPrivileges: { read: false }, + timelinePrivileges: { read: false }, + }); + + const wrapper = render( + + + + ); + + expect(wrapper.queryByTestId('timeline-notes-button-small')).not.toBeInTheDocument(); + expect(wrapper.queryByTestId('send-alert-to-timeline-button')).not.toBeInTheDocument(); + }); + }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/control_columns/row_action/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/control_columns/row_action/index.tsx index a56010182f138..35d7aadc17118 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/control_columns/row_action/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/control_columns/row_action/index.tsx @@ -26,6 +26,7 @@ import { useTourContext } from '../../guided_onboarding_tour'; import { AlertsCasesTourSteps, SecurityStepId } from '../../guided_onboarding_tour/tour_config'; import { NotesEventTypes, DocumentEventTypes } from '../../../lib/telemetry'; import { getMappedNonEcsValue } from '../../../utils/get_mapped_non_ecs_value'; +import { useUserPrivileges } from '../../user_privileges'; export type RowActionProps = EuiDataGridCellValueElementProps & { columnHeaders: ColumnHeaderOptions[]; @@ -97,6 +98,11 @@ const RowActionComponent = ({ const securitySolutionNotesDisabled = useIsExperimentalFeatureEnabled( 'securitySolutionNotesDisabled' ); + const { + notesPrivileges: { read: canReadNotes }, + timelinePrivileges: { read: canReadTimelines }, + } = useUserPrivileges(); + const showNotes = canReadNotes && !securitySolutionNotesDisabled; const handleOnEventDetailPanelOpened = useCallback(() => { openFlyout({ @@ -181,7 +187,8 @@ const RowActionComponent = ({ setEventsLoading={setEventsLoading} setEventsDeleted={setEventsDeleted} refetch={refetch} - showNotes={!securitySolutionNotesDisabled} + showNotes={showNotes} + disableTimelineAction={!canReadTimelines} /> )} diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/event_details/investigate_in_timeline_button.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/event_details/investigate_in_timeline_button.test.tsx index c9b2312c28f5e..6235dc77da438 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/event_details/investigate_in_timeline_button.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/event_details/investigate_in_timeline_button.test.tsx @@ -11,14 +11,19 @@ import React from 'react'; import { InvestigateInTimelineButton } from './investigate_in_timeline_button'; import { TestProviders } from '../../mock'; import { getDataProvider } from './use_action_cell_data_provider'; +import { useUserPrivileges } from '../user_privileges'; import { ACTION_INVESTIGATE_IN_TIMELINE } from '../../../detections/components/alerts_table/translations'; jest.mock('../../lib/kibana'); +jest.mock('../user_privileges'); describe('InvestigateInTimelineButton', () => { describe('When all props are provided', () => { test('it should display the add to timeline button', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { read: true }, + }); const dataProviders = ['127.0.0.1', '::1', '10.1.2.3', '2001:0DB8:AC10:FE01::'].map( (ipValue) => getDataProvider('host.ip', '', ipValue) ); @@ -28,6 +33,22 @@ describe('InvestigateInTimelineButton', () => { ); expect(screen.queryByLabelText(ACTION_INVESTIGATE_IN_TIMELINE)).toBeInTheDocument(); + expect(screen.queryByLabelText(ACTION_INVESTIGATE_IN_TIMELINE)).not.toBeDisabled(); + }); + + it('should be disabled when the user has insufficient privileges', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { read: false }, + }); + const dataProviders = ['127.0.0.1', '::1', '10.1.2.3', '2001:0DB8:AC10:FE01::'].map( + (ipValue) => getDataProvider('host.ip', '', ipValue) + ); + render( + + + + ); + expect(screen.queryByLabelText(ACTION_INVESTIGATE_IN_TIMELINE)).toBeDisabled(); }); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/event_details/investigate_in_timeline_button.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/event_details/investigate_in_timeline_button.tsx index 506b6c768494f..7b5549822793b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/event_details/investigate_in_timeline_button.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/event_details/investigate_in_timeline_button.tsx @@ -13,6 +13,7 @@ import type { Filter } from '@kbn/es-query'; import type { TimeRange } from '../../store/inputs/model'; import type { DataProvider } from '../../../../common/types'; import { ACTION_INVESTIGATE_IN_TIMELINE } from '../../../detections/components/alerts_table/translations'; +import { useUserPrivileges } from '../user_privileges'; import { useInvestigateInTimeline } from '../../hooks/timeline/use_investigate_in_timeline'; export interface InvestigateInTimelineButtonProps { @@ -37,6 +38,10 @@ export interface InvestigateInTimelineButtonProps { iconType?: IconType; children?: React.ReactNode; flush?: EuiButtonEmptyProps['flush']; + /** + * Data test subject string for testing + */ + ['data-test-subj']?: string; } /** @@ -54,6 +59,8 @@ export const InvestigateInTimelineButton: FC< keepDataView, iconType, flush, + isDisabled, + 'data-test-subj': dataTestSubj, ...rest }) => { const { investigateInTimeline } = useInvestigateInTimeline(); @@ -65,6 +72,11 @@ export const InvestigateInTimelineButton: FC< keepDataView, }); }, [dataProviders, filters, timeRange, keepDataView, investigateInTimeline]); + const { + timelinePrivileges: { read: canUseTimeline }, + } = useUserPrivileges(); + + const disabled = !canUseTimeline || isDisabled; return asEmptyButton ? ( {children} ) : ( - + {children} ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.test.tsx index 3d93dd19cf691..037f9f2c8a52a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.test.tsx @@ -17,8 +17,10 @@ import { licenseService } from '../../hooks/use_license'; import { mockHistory } from '../../mock/router'; import { DEFAULT_EVENTS_STACK_BY_VALUE } from './histogram_configurations'; import { useIsExperimentalFeatureEnabled } from '../../hooks/use_experimental_features'; +import { useUserPrivileges } from '../user_privileges'; jest.mock('../../hooks/use_experimental_features'); +jest.mock('../user_privileges'); const mockGetDefaultControlColumn = jest.fn(); jest.mock('../../../timelines/components/timeline/body/control_columns', () => ({ @@ -103,6 +105,9 @@ describe('EventsQueryTabBody', () => { beforeEach(() => { (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(false); + (useUserPrivileges as jest.Mock).mockReturnValue({ + notesPrivileges: { read: true }, + }); jest.clearAllMocks(); }); @@ -216,7 +221,19 @@ describe('EventsQueryTabBody', () => { expect(mockGetDefaultControlColumn).toHaveBeenCalledWith(4); }); - it('should 6 columns on Action bar for Enterprise user', () => { + it('should have 4 columns on Action bar for non-Enterprise user and if user does not have Notes privileges', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ notesPrivileges: { read: false } }); + + render( + + + + ); + + expect(mockGetDefaultControlColumn).toHaveBeenCalledWith(4); + }); + + it('should have 6 columns on Action bar for Enterprise user', () => { const licenseServiceMock = licenseService as jest.Mocked; licenseServiceMock.isEnterprise.mockReturnValue(true); @@ -229,7 +246,7 @@ describe('EventsQueryTabBody', () => { expect(mockGetDefaultControlColumn).toHaveBeenCalledWith(6); }); - it('should 6 columns on Action bar for Enterprise user and securitySolutionNotesDisabled is true', () => { + it('should have 5 columns on Action bar for Enterprise user and securitySolutionNotesDisabled is true', () => { const licenseServiceMock = licenseService as jest.Mocked; licenseServiceMock.isEnterprise.mockReturnValue(true); (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(true); @@ -242,4 +259,18 @@ describe('EventsQueryTabBody', () => { expect(mockGetDefaultControlColumn).toHaveBeenCalledWith(5); }); + + it('should have 5 columns on Action bar for Enterprise user and if user does not have Notes privileges', () => { + const licenseServiceMock = licenseService as jest.Mocked; + licenseServiceMock.isEnterprise.mockReturnValue(true); + (useUserPrivileges as jest.Mock).mockReturnValue({ notesPrivileges: { read: false } }); + + render( + + + + ); + + expect(mockGetDefaultControlColumn).toHaveBeenCalledWith(5); + }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.tsx index 2bb51df635380..48b65e8ec1d79 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.tsx @@ -46,6 +46,7 @@ import { } from '../../utils/global_query_string/helpers'; import type { BulkActionsProp } from '../toolbar/bulk_actions/types'; import { SecurityCellActionsTrigger } from '../cell_actions'; +import { useUserPrivileges } from '../user_privileges'; export const ALERTS_EVENTS_HISTOGRAM_ID = 'alertsOrEventsHistogramQuery'; @@ -61,6 +62,15 @@ export type EventsQueryTabBodyComponentProps = QueryTabBodyProps & { const EXTERNAL_ALERTS_URL_PARAM = 'onlyExternalAlerts'; +// we show a maximum of 6 action buttons +// - open flyout +// - investigate in timeline +// - 3-dot menu for more actions +// - add new note +// - session view +// - analyzer graph +const MAX_ACTION_BUTTON_COUNT = 6; + const EventsQueryTabBodyComponent: React.FC = ({ additionalFilters, deleteQuery, @@ -70,17 +80,27 @@ const EventsQueryTabBodyComponent: React.FC = startDate, tableId, }) => { + let ACTION_BUTTON_COUNT = MAX_ACTION_BUTTON_COUNT; + const dispatch = useDispatch(); const { globalFullScreen } = useGlobalFullScreen(); const [defaultNumberFormat] = useUiSetting$(DEFAULT_NUMBER_FORMAT); + const isEnterprisePlus = useLicense().isEnterprise(); - let ACTION_BUTTON_COUNT = isEnterprisePlus ? 6 : 5; + if (!isEnterprisePlus) { + ACTION_BUTTON_COUNT--; + } + + const { + notesPrivileges: { read: canReadNotes }, + } = useUserPrivileges(); const securitySolutionNotesDisabled = useIsExperimentalFeatureEnabled( 'securitySolutionNotesDisabled' ); - if (securitySolutionNotesDisabled) { + if (!canReadNotes || securitySolutionNotesDisabled) { ACTION_BUTTON_COUNT--; } + const leadingControlColumns = useMemo( () => getDefaultControlColumn(ACTION_BUTTON_COUNT), [ACTION_BUTTON_COUNT] diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/filter_by_assignees_popover/filter_by_assignees_popover.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/filter_by_assignees_popover/filter_by_assignees_popover.test.tsx index fbfe0eb705b91..5e912e9e5c71d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/filter_by_assignees_popover/filter_by_assignees_popover.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/filter_by_assignees_popover/filter_by_assignees_popover.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { render } from '@testing-library/react'; +import { render, fireEvent } from '@testing-library/react'; import { FilterByAssigneesPopover } from './filter_by_assignees_popover'; import { TestProviders } from '../../mock'; @@ -110,14 +110,14 @@ describe('', () => { const onUsersChangeMock = jest.fn(); const { getByTestId, getByText } = renderFilterByAssigneesPopover([], onUsersChangeMock); - getByTestId(FILTER_BY_ASSIGNEES_BUTTON).click(); + fireEvent.click(getByTestId(FILTER_BY_ASSIGNEES_BUTTON)); - getByText('User 1').click(); - getByText('User 2').click(); - getByText('User 3').click(); - getByText('User 3').click(); - getByText('User 2').click(); - getByText('User 1').click(); + fireEvent.click(getByText('User 1')); + fireEvent.click(getByText('User 2')); + fireEvent.click(getByText('User 3')); + fireEvent.click(getByText('User 3')); + fireEvent.click(getByText('User 2')); + fireEvent.click(getByText('User 1')); expect(onUsersChangeMock).toHaveBeenCalledTimes(6); expect(onUsersChangeMock.mock.calls).toEqual([ diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/actions.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/actions.test.tsx index 818b56556e768..f4d264f9e3e3d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/actions.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/actions.test.tsx @@ -72,7 +72,7 @@ jest.mock('../../lib/kibana', () => { navigateToApp: jest.fn(), getUrlForApp: jest.fn(), capabilities: { - siem: { crud_alerts: true, read_alerts: true }, + siemV2: { crud_alerts: true, read_alerts: true }, }, }, cases: mockCasesContract(), @@ -600,4 +600,28 @@ describe('Actions', () => { expect(wrapper.find('[data-test-subj="pin-event"]').exists()).toBeTruthy(); }); }); + + describe('Timeline action', () => { + test('should show timeline action by default', () => { + const wrapper = mount( + + + + ); + + expect( + wrapper.find('[data-test-subj="send-alert-to-timeline-button"]').exists() + ).toBeTruthy(); + }); + + test('should hide timeline action when disableTimelineAction = true', () => { + const wrapper = mount( + + + + ); + + expect(wrapper.find('[data-test-subj="send-alert-to-timeline-button"]').exists()).toBeFalsy(); + }); + }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/actions.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/actions.tsx index 4775b8f889028..dd2107efd1d88 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/actions.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/actions.tsx @@ -73,6 +73,7 @@ const ActionsComponent: React.FC = ({ refetch, toggleShowNotes, disablePinAction = true, + disableTimelineAction = false, }) => { const dispatch = useDispatch(); @@ -339,7 +340,7 @@ const ActionsComponent: React.FC = ({ )} <> - {timelineId !== TimelineId.active && ( + {!disableTimelineAction && timelineId !== TimelineId.active && ( { jest.clearAllMocks(); useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true, read: true }, + notesPrivileges: { crud: true, read: true }, endpointPrivileges: getEndpointPrivilegesInitialStateMock(), }); @@ -135,13 +135,13 @@ describe('AddEventNoteAction', () => { }); describe('button state', () => { - test('should disable the add note button when the user does NOT have crud privileges', () => { + test('should disable the add note button when the user does NOT have crud privileges and no notes have been created', () => { useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: false, read: true }, + notesPrivileges: { crud: false, read: true }, endpointPrivileges: getEndpointPrivilegesInitialStateMock(), }); - renderTestComponent(); + renderTestComponent({ notesCount: 0 }); expect(screen.getByTestId('timeline-notes-button-small-mock')).toHaveProperty( 'disabled', @@ -151,7 +151,7 @@ describe('AddEventNoteAction', () => { test('should enable the add note button when the user has crud privileges', () => { useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true, read: true }, + notesPrivileges: { crud: true, read: true }, endpointPrivileges: getEndpointPrivilegesInitialStateMock(), }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/add_note_icon_item.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/add_note_icon_item.tsx index f931042863a62..f95ebca1ad52a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/add_note_icon_item.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/add_note_icon_item.tsx @@ -24,7 +24,13 @@ const NOTES_ADD_TOOLTIP = i18n.translate( defaultMessage: 'Add note', } ); -const NOTES_COUNT_TOOLTIP = ({ notesCount }: { notesCount: number }) => +const NO_NOTES_TOOLTIP = i18n.translate( + 'xpack.securitySolution.timeline.body.notes.addNoteTooltip', + { + defaultMessage: 'No notes available', + } +); +const ADD_NOTES_COUNT_TOOLTIP = ({ notesCount }: { notesCount: number }) => i18n.translate( 'xpack.securitySolution.timeline.body.notes.addNote.multipleNotesAvailableTooltip', { @@ -34,6 +40,16 @@ const NOTES_COUNT_TOOLTIP = ({ notesCount }: { notesCount: number }) => } ); +const VIEW_NOTES_COUNT_TOOLTIP = ({ notesCount }: { notesCount: number }) => + i18n.translate( + 'xpack.securitySolution.timeline.body.notes.addNote.multipleNotesAvailableTooltip', + { + values: { notesCount }, + defaultMessage: + '{notesCount} {notesCount, plural, one {note} other {notes} } available. Click to view {notesCount, plural, one {it} other {them}}.', + } + ); + interface AddEventNoteActionProps { ariaLabel?: string; timelineType: TimelineType; @@ -52,22 +68,36 @@ const AddEventNoteActionComponent: React.FC = ({ eventId, notesCount, }) => { - const { kibanaSecuritySolutionsPrivileges } = useUserPrivileges(); + const { + notesPrivileges: { crud: canAddNotes, read: canViewNotes }, + } = useUserPrivileges(); - const NOTES_TOOLTIP = useMemo( - () => (notesCount > 0 ? NOTES_COUNT_TOOLTIP({ notesCount }) : NOTES_ADD_TOOLTIP), - [notesCount] - ); + const tooltip = useMemo(() => { + if (timelineType === TimelineTypeEnum.template) { + return NOTES_DISABLE_TOOLTIP; + } + if (canAddNotes) { + return notesCount > 0 ? ADD_NOTES_COUNT_TOOLTIP({ notesCount }) : NOTES_ADD_TOOLTIP; + } + if (canViewNotes) { + return notesCount > 0 ? VIEW_NOTES_COUNT_TOOLTIP({ notesCount }) : NO_NOTES_TOOLTIP; + } + + // we can return an empty string for tooltip because the icon is actually no shown at all + return ''; + }, [canAddNotes, canViewNotes, notesCount, timelineType]); + + const disabled = useMemo(() => !canAddNotes && notesCount === 0, [canAddNotes, notesCount]); return ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/pin_event_action.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/pin_event_action.test.tsx index 33358264d6417..b830b4dc1d6e0 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/pin_event_action.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/pin_event_action.test.tsx @@ -25,7 +25,7 @@ describe('PinEventAction', () => { describe('isDisabled', () => { test('it disables the pin event button when the user does NOT have crud privileges', () => { useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: false, read: true }, + timelinePrivileges: { crud: false, read: true }, endpointPrivileges: getEndpointPrivilegesInitialStateMock(), }); @@ -46,7 +46,7 @@ describe('PinEventAction', () => { test('it enables the pin event button when the user has crud privileges', () => { useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true, read: true }, + timelinePrivileges: { crud: true, read: true }, endpointPrivileges: getEndpointPrivilegesInitialStateMock(), }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/pin_event_action.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/pin_event_action.tsx index b2569ac58eaf9..2322c2c985094 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/pin_event_action.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_actions/pin_event_action.tsx @@ -31,7 +31,7 @@ const PinEventActionComponent: React.FC = ({ eventIsPinned, timelineType, }) => { - const { kibanaSecuritySolutionsPrivileges } = useUserPrivileges(); + const { timelinePrivileges } = useUserPrivileges(); const tooltipContent = useMemo( () => getPinTooltip({ @@ -51,7 +51,7 @@ const PinEventActionComponent: React.FC = ({ ariaLabel={ariaLabel} allowUnpinning={!eventHasNotes(noteIds)} data-test-subj="pin-event" - isDisabled={kibanaSecuritySolutionsPrivileges.crud === false} + isDisabled={timelinePrivileges.crud === false} isAlert={isAlert} onClick={onPinClicked} pinned={eventIsPinned} diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/links/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/links/index.tsx index 54bac0a0c77db..9481bf3819d3d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/links/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/links/index.tsx @@ -122,6 +122,34 @@ const UserDetailsLinkComponent: React.FC<{ export const UserDetailsLink = React.memo(UserDetailsLinkComponent); +const ServiceDetailsLinkComponent: React.FC<{ + children?: React.ReactNode; + serviceName?: string; + onClick?: (e: SyntheticEvent) => void; +}> = ({ children, onClick: onClickParam, serviceName }) => { + const { telemetry } = useKibana().services; + + const onClick = useCallback( + (e: SyntheticEvent) => { + telemetry.reportEvent(EntityEventTypes.EntityDetailsClicked, { entity: EntityType.service }); + if (onClickParam) { + onClickParam(e); + } + }, + [onClickParam, telemetry] + ); + + return onClickParam ? ( + + {children ? children : serviceName} + + ) : ( + serviceName + ); +}; + +export const ServiceDetailsLink = React.memo(ServiceDetailsLinkComponent); + export interface HostDetailsLinkProps { children?: React.ReactNode; /** `Component` is only used with `EuiDataGrid`; the grid keeps a reference to `Component` for show / hide functionality */ @@ -222,6 +250,8 @@ export const EntityDetailsLink = ({ return ; } else if (entityType === EntityType.user) { return ; + } else if (entityType === EntityType.service) { + return ; } return entityName; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/editor.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/editor.tsx index 402c27efab56d..c1dcb839f9c0d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/editor.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/editor.tsx @@ -22,6 +22,7 @@ import type { ContextShape } from '@elastic/eui/src/components/markdown_editor/m import { uiPlugins, parsingPlugins, processingPlugins } from './plugins'; import { useUpsellingMessage } from '../../hooks/use_upselling'; +import { useUserPrivileges } from '../user_privileges'; interface MarkdownEditorProps { onChange: (content: string) => void; @@ -76,14 +77,18 @@ const MarkdownEditorComponent = forwardRef { return includePlugins ? uiPlugins({ insightsUpsellingMessage, interactionsUpsellingMessage, + canSeeTimeline, }) : undefined; - }, [includePlugins, insightsUpsellingMessage, interactionsUpsellingMessage]); + }, [includePlugins, canSeeTimeline, insightsUpsellingMessage, interactionsUpsellingMessage]); // @ts-expect-error update types useImperativeHandle(ref, () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/plugins/index.ts b/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/plugins/index.ts index b6067ac21eb1d..c76eb39a20c09 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/plugins/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/plugins/index.ts @@ -23,9 +23,11 @@ export const platinumOnlyPluginTokens = [insightMarkdownPlugin.insightPrefix]; export const uiPlugins = ({ insightsUpsellingMessage, interactionsUpsellingMessage, + canSeeTimeline, }: { insightsUpsellingMessage?: string; interactionsUpsellingMessage?: string; + canSeeTimeline: boolean; }) => { const currentPlugins = nonStatefulUiPlugins.map((plugin) => plugin.name); const insightPluginWithLicense = insightMarkdownPlugin.plugin({ @@ -33,6 +35,7 @@ export const uiPlugins = ({ }); const timelinePluginWithLicense = timelineMarkdownPlugin.plugin({ interactionsUpsellingMessage, + canSeeTimeline, }); const osqueryPluginWithLicense = osqueryMarkdownPlugin.plugin({ interactionsUpsellingMessage, diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/plugins/timeline/plugin.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/plugins/timeline/plugin.tsx index 4d5b2e14e0d95..1b1f368ffcad0 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/plugins/timeline/plugin.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/plugins/timeline/plugin.tsx @@ -77,15 +77,17 @@ const TimelineEditor = memo(TimelineEditorComponent); export const plugin = ({ interactionsUpsellingMessage, + canSeeTimeline, }: { interactionsUpsellingMessage?: string; + canSeeTimeline: boolean; }): EuiMarkdownEditorUiPlugin => { return { name: ID, button: { label: interactionsUpsellingMessage ?? i18n.INSERT_TIMELINE, iconType: 'timeline', - isDisabled: !!interactionsUpsellingMessage, + isDisabled: !canSeeTimeline || !!interactionsUpsellingMessage, }, helpText: ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/plugins/timeline/processor.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/plugins/timeline/processor.tsx index c2460cf7f5d19..4d0c1c7ae2268 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/plugins/timeline/processor.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/plugins/timeline/processor.tsx @@ -13,6 +13,7 @@ import { useTimelineClick } from '../../../../utils/timeline/use_timeline_click' import type { TimelineProps } from './types'; import * as i18n from './translations'; import { useAppToasts } from '../../../../hooks/use_app_toasts'; +import { useUserPrivileges } from '../../../user_privileges'; export const TimelineMarkDownRendererComponent: React.FC = ({ id, @@ -22,6 +23,10 @@ export const TimelineMarkDownRendererComponent: React.FC = ({ const { addError } = useAppToasts(); const interactionsUpsellingMessage = useUpsellingMessage('investigation_guide_interactions'); + const { + timelinePrivileges: { read: canReadTimelines }, + } = useUserPrivileges(); + const isDisabled = !!interactionsUpsellingMessage || !canReadTimelines; const handleTimelineClick = useTimelineClick(); @@ -43,7 +48,7 @@ export const TimelineMarkDownRendererComponent: React.FC = ({ {title} diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/user_privileges/endpoint/use_endpoint_privileges.test.ts b/x-pack/solutions/security/plugins/security_solution/public/common/components/user_privileges/endpoint/use_endpoint_privileges.test.ts index 2cfe665697b93..1711e4f224411 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/user_privileges/endpoint/use_endpoint_privileges.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/user_privileges/endpoint/use_endpoint_privileges.test.ts @@ -53,7 +53,7 @@ describe('When using useEndpointPrivileges hook', () => { catalogue: {}, management: {}, navLinks: {}, - siem: { + siemV2: { crud: true, show: true, }, diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/user_privileges/user_privileges_context.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/user_privileges/user_privileges_context.tsx index b17a043170e80..471adae7b2ee2 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/user_privileges/user_privileges_context.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/user_privileges/user_privileges_context.tsx @@ -7,17 +7,21 @@ import React, { createContext, useEffect, useState } from 'react'; import type { Capabilities } from '@kbn/core/types'; -import { SERVER_APP_ID } from '../../../../common/constants'; +import { SECURITY_FEATURE_ID } from '../../../../common/constants'; import { useFetchListPrivileges } from '../../../detections/components/user_privileges/use_fetch_list_privileges'; import { useFetchDetectionEnginePrivileges } from '../../../detections/components/user_privileges/use_fetch_detection_engine_privileges'; import { getEndpointPrivilegesInitialState, useEndpointPrivileges } from './endpoint'; import type { EndpointPrivileges } from '../../../../common/endpoint/types'; +import { extractTimelineCapabilities } from '../../utils/timeline_capabilities'; +import { extractNotesCapabilities } from '../../utils/notes_capabilities'; export interface UserPrivilegesState { listPrivileges: ReturnType; detectionEnginePrivileges: ReturnType; endpointPrivileges: EndpointPrivileges; kibanaSecuritySolutionsPrivileges: { crud: boolean; read: boolean }; + timelinePrivileges: { crud: boolean; read: boolean }; + notesPrivileges: { crud: boolean; read: boolean }; } export const initialUserPrivilegesState = (): UserPrivilegesState => ({ @@ -25,6 +29,8 @@ export const initialUserPrivilegesState = (): UserPrivilegesState => ({ detectionEnginePrivileges: { loading: false, error: undefined, result: undefined }, endpointPrivileges: getEndpointPrivilegesInitialState(), kibanaSecuritySolutionsPrivileges: { crud: false, read: false }, + timelinePrivileges: { crud: false, read: false }, + notesPrivileges: { crud: false, read: false }, }); export const UserPrivilegesContext = createContext( initialUserPrivilegesState() @@ -39,8 +45,8 @@ export const UserPrivilegesProvider = ({ kibanaCapabilities, children, }: UserPrivilegesProviderProps) => { - const crud: boolean = kibanaCapabilities[SERVER_APP_ID].crud === true; - const read: boolean = kibanaCapabilities[SERVER_APP_ID].show === true; + const crud: boolean = kibanaCapabilities[SECURITY_FEATURE_ID].crud === true; + const read: boolean = kibanaCapabilities[SECURITY_FEATURE_ID].show === true; const [kibanaSecuritySolutionsPrivileges, setKibanaSecuritySolutionsPrivileges] = useState({ crud, read, @@ -50,6 +56,34 @@ export const UserPrivilegesProvider = ({ const detectionEnginePrivileges = useFetchDetectionEnginePrivileges(read); const endpointPrivileges = useEndpointPrivileges(); + const [timelinePrivileges, setTimelinePrivileges] = useState( + extractTimelineCapabilities(kibanaCapabilities) + ); + const [notesPrivileges, setNotesPrivileges] = useState( + extractNotesCapabilities(kibanaCapabilities) + ); + + useEffect(() => { + setNotesPrivileges((currPrivileges) => { + const { read: notesRead, crud: notesCrud } = extractNotesCapabilities(kibanaCapabilities); + if (currPrivileges.read !== notesRead || currPrivileges.crud !== notesCrud) { + return { read: notesRead, crud: notesCrud }; + } + return currPrivileges; + }); + }, [kibanaCapabilities]); + + useEffect(() => { + setTimelinePrivileges((currPrivileges) => { + const { read: timelineRead, crud: timelineCrud } = + extractTimelineCapabilities(kibanaCapabilities); + if (currPrivileges.read !== timelineRead || currPrivileges.crud !== timelineCrud) { + return { read: timelineRead, crud: timelineCrud }; + } + return currPrivileges; + }); + }, [kibanaCapabilities]); + useEffect(() => { setKibanaSecuritySolutionsPrivileges((currPrivileges) => { if (currPrivileges.read !== read || currPrivileges.crud !== crud) { @@ -66,6 +100,8 @@ export const UserPrivilegesProvider = ({ detectionEnginePrivileges, endpointPrivileges, kibanaSecuritySolutionsPrivileges, + timelinePrivileges, + notesPrivileges, }} > {children} diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts b/x-pack/solutions/security/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts index 07a9220b3dfa4..c24142f63a843 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts @@ -32,7 +32,7 @@ import { DEFAULT_RULES_TABLE_REFRESH_SETTING, DEFAULT_RULE_REFRESH_INTERVAL_ON, DEFAULT_RULE_REFRESH_INTERVAL_VALUE, - SERVER_APP_ID, + SECURITY_FEATURE_ID, } from '../../../../common/constants'; import type { StartServices } from '../../../types'; import { createSecuritySolutionStorageMock } from '../../mock/mock_local_storage'; @@ -201,7 +201,11 @@ export const createStartServicesMock = ( ...core.application, capabilities: { ...core.application.capabilities, - [SERVER_APP_ID]: { + [SECURITY_FEATURE_ID]: { + crud: true, + read: true, + }, + securitySolutionTimeline: { crud: true, read: true, }, diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/links/links.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/links/links.test.tsx index 7ecd8541e909f..14c14246e44d3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/links/links.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/links/links.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { CASES_FEATURE_ID, SecurityPageName, SERVER_APP_ID } from '../../../common/constants'; +import { CASES_FEATURE_ID, SecurityPageName, SECURITY_FEATURE_ID } from '../../../common/constants'; import type { Capabilities } from '@kbn/core/types'; import { mockGlobalState, TestProviders } from '../mock'; import type { ILicense, LicenseType } from '@kbn/licensing-plugin/common/types'; @@ -53,7 +53,7 @@ const mockExperimentalDefaults = mockGlobalState.app.enableExperimental; const mockCapabilities = { [CASES_FEATURE_ID]: { read_cases: true, crud_cases: true }, - [SERVER_APP_ID]: { show: true }, + [SECURITY_FEATURE_ID]: { show: true }, } as unknown as Capabilities; const fakePageId = 'fakePage'; @@ -115,7 +115,7 @@ describe('Security links', () => { id: SecurityPageName.network, title: 'Network', path: '/network', - capabilities: [`${CASES_FEATURE_ID}.read_cases`, `${SERVER_APP_ID}.show`], + capabilities: [`${CASES_FEATURE_ID}.read_cases`, `${SECURITY_FEATURE_ID}.show`], experimentalKey: 'flagEnabled' as unknown as keyof typeof mockExperimentalDefaults, hideWhenExperimentalKey: 'flagDisabled' as unknown as keyof typeof mockExperimentalDefaults, licenseType: 'basic' as const, @@ -432,7 +432,7 @@ describe('Security links', () => { }); describe('hasCapabilities', () => { - const siemShow = 'siem.show'; + const siemShow = 'siemV2.show'; const createCases = 'securitySolutionCasesV2.create_cases'; const readCases = 'securitySolutionCasesV2.read_cases'; const pushCases = 'securitySolutionCasesV2.push_cases'; @@ -442,18 +442,20 @@ describe('Security links', () => { }); it('returns true when the capability requested is specified as a single value', () => { - expect(hasCapabilities(createCapabilities({ siem: { show: true } }), siemShow)).toBeTruthy(); + expect( + hasCapabilities(createCapabilities({ siemV2: { show: true } }), siemShow) + ).toBeTruthy(); }); it('returns true when the capability requested is a single entry in an array', () => { expect( - hasCapabilities(createCapabilities({ siem: { show: true } }), [siemShow]) + hasCapabilities(createCapabilities({ siemV2: { show: true } }), [siemShow]) ).toBeTruthy(); }); it("returns true when the capability requested is a single entry in an AND'd array format", () => { expect( - hasCapabilities(createCapabilities({ siem: { show: true } }), [[siemShow]]) + hasCapabilities(createCapabilities({ siemV2: { show: true } }), [[siemShow]]) ).toBeTruthy(); }); @@ -461,7 +463,7 @@ describe('Security links', () => { expect( hasCapabilities( createCapabilities({ - siem: { show: true }, + siemV2: { show: true }, securitySolutionCasesV2: { create_cases: false }, }), [siemShow, createCases] @@ -473,7 +475,7 @@ describe('Security links', () => { expect( hasCapabilities( createCapabilities({ - siem: { show: false }, + siemV2: { show: false }, securitySolutionCasesV2: { create_cases: true }, }), [siemShow, createCases] @@ -485,7 +487,7 @@ describe('Security links', () => { expect( hasCapabilities( createCapabilities({ - siem: { show: true }, + siemV2: { show: true }, securitySolutionCasesV2: { create_cases: false }, }), [readCases, createCases] @@ -497,7 +499,7 @@ describe('Security links', () => { expect( hasCapabilities( createCapabilities({ - siem: { show: true }, + siemV2: { show: true }, securitySolutionCasesV2: { read_cases: true, create_cases: true }, }), [[readCases, createCases]] @@ -509,7 +511,7 @@ describe('Security links', () => { expect( hasCapabilities( createCapabilities({ - siem: { show: false }, + siemV2: { show: false }, securitySolutionCasesV2: { read_cases: false, create_cases: true }, }), [siemShow, [readCases, createCases]] @@ -521,7 +523,7 @@ describe('Security links', () => { expect( hasCapabilities( createCapabilities({ - siem: { show: true }, + siemV2: { show: true }, securitySolutionCasesV2: { read_cases: false, create_cases: true }, }), [siemShow, [readCases, createCases]] @@ -533,7 +535,7 @@ describe('Security links', () => { expect( hasCapabilities( createCapabilities({ - siem: { show: true }, + siemV2: { show: true }, securitySolutionCasesV2: { read_cases: false, create_cases: true, push_cases: false }, }), [ diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/mock/create_store.ts b/x-pack/solutions/security/plugins/security_solution/public/common/mock/create_store.ts index 91eac259e61f2..09cb3f842f8ed 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/mock/create_store.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/common/mock/create_store.ts @@ -12,12 +12,11 @@ import { createStore } from '../store'; import { mockGlobalState } from './global_state'; import type { AppAction } from '../store/actions'; import type { Immutable } from '../../../common/endpoint/types'; -import type { StartServices } from '../../types'; import { createSecuritySolutionStorageMock } from './mock_local_storage'; +import { createStartServicesMock } from '../lib/kibana/kibana_react.mock'; const { storage: storageMock } = createSecuritySolutionStorageMock(); - -const kibanaMock = {} as unknown as StartServices; +const kibanaMock = createStartServicesMock(); export const createMockStore = ( state: State = mockGlobalState, diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/mock/test_providers.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/mock/test_providers.tsx index d5f1830857823..73490ece96624 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/mock/test_providers.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/mock/test_providers.tsx @@ -140,7 +140,7 @@ const TestProvidersWithPrivilegesComponent: React.FC = ({ | null = null; @@ -71,7 +71,7 @@ export const createStoreFactory = async ( index_mapping_outdated: null, }; try { - if (coreStart.application.capabilities[SERVER_APP_ID].show === true) { + if (hasAccessToSecuritySolution(coreStart.application.capabilities)) { signal = await coreStart.http.fetch(DETECTION_ENGINE_INDEX_URL, { version: '2023-10-31', method: 'GET', diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/utils/notes_capabilities.ts b/x-pack/solutions/security/plugins/security_solution/public/common/utils/notes_capabilities.ts new file mode 100644 index 0000000000000..895a560d61b5e --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/common/utils/notes_capabilities.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 type { Capabilities } from '@kbn/core/types'; + +export function extractNotesCapabilities(capabilities: Capabilities) { + const notesCrud = capabilities.securitySolutionNotes?.crud === true; + const notesRead = capabilities.securitySolutionNotes?.read === true; + return { read: notesRead, crud: notesCrud }; +} diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/utils/timeline/use_show_timeline.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/utils/timeline/use_show_timeline.test.tsx index 1d3a758b70199..9bc192880ea89 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/utils/timeline/use_show_timeline.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/utils/timeline/use_show_timeline.test.tsx @@ -10,9 +10,12 @@ import { allowedExperimentalValues } from '../../../../common/experimental_featu import { UpsellingService } from '@kbn/security-solution-upselling/service'; import { updateAppLinks } from '../../links'; import { appLinks } from '../../../app_links'; +import { useUserPrivileges } from '../../components/user_privileges'; import { useShowTimeline } from './use_show_timeline'; import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; +jest.mock('../../components/user_privileges'); + const mockUseLocation = jest.fn().mockReturnValue({ pathname: '/overview' }); jest.mock('react-router-dom', () => { const original = jest.requireActual('react-router-dom'); @@ -43,7 +46,7 @@ jest.mock('../../lib/kibana', () => { ...original.useKibana().services, application: { capabilities: { - siem: { + siemV2: { show: mockSiemUserCanRead(), }, }, @@ -58,6 +61,10 @@ const mockUiSettingsClient = uiSettingsServiceMock.createStartContract(); describe('use show timeline', () => { beforeAll(() => { + (useUserPrivileges as unknown as jest.Mock).mockReturnValue({ + timelinePrivileges: { read: true }, + }); + // initialize all App links before running test updateAppLinks(appLinks, { experimentalFeatures: allowedExperimentalValues, @@ -66,7 +73,7 @@ describe('use show timeline', () => { management: {}, catalogue: {}, actions: { show: true, crud: true }, - siem: { + siemV2: { show: true, crud: true, }, @@ -98,6 +105,24 @@ describe('use show timeline', () => { const { result } = renderHook(() => useShowTimeline()); await waitFor(() => expect(result.current).toEqual([false])); }); + it('hides timeline for users without timeline access', async () => { + (useUserPrivileges as unknown as jest.Mock).mockReturnValue({ + timelinePrivileges: { read: false }, + }); + + const { result } = renderHook(() => useShowTimeline()); + const showTimeline = result.current; + expect(showTimeline).toEqual([false]); + }); +}); +it('shows timeline for users with timeline read access', async () => { + (useUserPrivileges as unknown as jest.Mock).mockReturnValue({ + timelinePrivileges: { read: true }, + }); + + const { result } = renderHook(() => useShowTimeline()); + const showTimeline = result.current; + expect(showTimeline).toEqual([true]); }); describe('sourcererDataView', () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/utils/timeline/use_show_timeline.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/utils/timeline/use_show_timeline.tsx index c6554b80c2626..239ead8b4e481 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/utils/timeline/use_show_timeline.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/utils/timeline/use_show_timeline.tsx @@ -8,14 +8,18 @@ import { useMemo } from 'react'; import { useLocation } from 'react-router-dom'; import { useShowTimelineForGivenPath } from './use_show_timeline_for_path'; +import { useUserPrivileges } from '../../components/user_privileges'; export const useShowTimeline = () => { const { pathname } = useLocation(); const getIsTimelineVisible = useShowTimelineForGivenPath(); + const { + timelinePrivileges: { read: canSeeTimeline }, + } = useUserPrivileges(); const showTimeline = useMemo( - () => getIsTimelineVisible(pathname), - [pathname, getIsTimelineVisible] + () => canSeeTimeline && getIsTimelineVisible(pathname), + [pathname, canSeeTimeline, getIsTimelineVisible] ); return [showTimeline]; }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/utils/timeline/use_show_timeline_for_path.ts b/x-pack/solutions/security/plugins/security_solution/public/common/utils/timeline/use_show_timeline_for_path.ts index 0e7b208c2dd1d..30f5b078770b5 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/utils/timeline/use_show_timeline_for_path.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/common/utils/timeline/use_show_timeline_for_path.ts @@ -12,6 +12,7 @@ import { getLinksWithHiddenTimeline } from '../../links'; import { SourcererScopeName } from '../../../sourcerer/store/model'; import { useSourcererDataView } from '../../../sourcerer/containers'; import { useKibana } from '../../lib/kibana'; +import { hasAccessToSecuritySolution } from '../../../helpers_access'; const isTimelinePathVisible = (currentPath: string): boolean => { const groupLinksWithHiddenTimelinePaths = getLinksWithHiddenTimeline().map((l) => l.path); @@ -21,7 +22,12 @@ const isTimelinePathVisible = (currentPath: string): boolean => { export const useShowTimelineForGivenPath = () => { const { indicesExist, dataViewId } = useSourcererDataView(SourcererScopeName.timeline); - const userHasSecuritySolutionVisible = useKibana().services.application.capabilities.siem.show; + const { + services: { + application: { capabilities }, + }, + } = useKibana(); + const userHasSecuritySolutionVisible = hasAccessToSecuritySolution(capabilities); const isTimelineAllowed = useMemo( () => userHasSecuritySolutionVisible && (indicesExist || dataViewId === null), diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/utils/timeline_capabilities.ts b/x-pack/solutions/security/plugins/security_solution/public/common/utils/timeline_capabilities.ts new file mode 100644 index 0000000000000..b5340852ecbc0 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/common/utils/timeline_capabilities.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 type { Capabilities } from '@kbn/core/types'; + +export function extractTimelineCapabilities(capabilities: Capabilities) { + const timelineCrud = capabilities.securitySolutionTimeline?.crud === true; + const timelineRead = capabilities.securitySolutionTimeline?.read === true; + return { read: timelineRead, crud: timelineCrud }; +} diff --git a/x-pack/solutions/security/plugins/security_solution/public/dashboards/links.ts b/x-pack/solutions/security/plugins/security_solution/public/dashboards/links.ts index 0f4f8800578f6..a6914e76734a8 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/dashboards/links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/dashboards/links.ts @@ -5,7 +5,7 @@ * 2.0. */ import { i18n } from '@kbn/i18n'; -import { DASHBOARDS_PATH, SecurityPageName, SERVER_APP_ID } from '../../common/constants'; +import { DASHBOARDS_PATH, SecurityPageName, SECURITY_FEATURE_ID } from '../../common/constants'; import { DASHBOARDS } from '../app/translations'; import type { LinkItem } from '../common/links/types'; import { links as kubernetesLinks } from '../kubernetes/links'; @@ -33,7 +33,7 @@ export const dashboardsLinks: LinkItem = { title: DASHBOARDS, path: DASHBOARDS_PATH, globalNavPosition: 1, - capabilities: [`${SERVER_APP_ID}.show`], + capabilities: [`${SECURITY_FEATURE_ID}.show`], globalSearchKeywords: [ i18n.translate('xpack.securitySolution.appLinks.dashboards', { defaultMessage: 'Dashboards', diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation/components/eql_query_edit/eql_query_bar.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation/components/eql_query_edit/eql_query_bar.tsx index 6111d2e1a2d3d..0f12dcee977a1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation/components/eql_query_edit/eql_query_bar.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation/components/eql_query_edit/eql_query_bar.tsx @@ -190,6 +190,7 @@ export const EqlQueryBar: FC = ({ isInvalid={!isValid && !isValidating} value={fieldValue.query.query as string} onChange={handleChange} + aria-label={field.label} /> { it('renders correctly', () => { const mockField = useFormFieldMock(); const wrapper = shallow( - + ); expect(wrapper.find('[data-test-subj="schedule-item"]')).toHaveLength(1); }); - it('accepts a large number via user input', () => { + it('accepts user input', () => { const mockField = useFormFieldMock(); const wrapper = mount( - + ); @@ -47,17 +37,20 @@ describe('ScheduleItemField', () => { expect(mockField.setValue).toHaveBeenCalledWith('5000000s'); }); - it('clamps a number value greater than MAX_SAFE_INTEGER to MAX_SAFE_INTEGER', () => { - const unsafeInput = '99999999999999999999999'; - + it.each([ + [-10, -5], + [-5, 0], + [5, 10], + [60, 90], + ])('saturates a value "%s" lower than minValue', (unsafeInput, expected) => { const mockField = useFormFieldMock(); const wrapper = mount( ); @@ -67,21 +60,23 @@ describe('ScheduleItemField', () => { .last() .simulate('change', { target: { value: unsafeInput } }); - const expectedValue = `${Number.MAX_SAFE_INTEGER}s`; - expect(mockField.setValue).toHaveBeenCalledWith(expectedValue); + expect(mockField.setValue).toHaveBeenCalledWith(`${expected}s`); }); - it('converts a non-numeric value to 0', () => { - const unsafeInput = 'this is not a number'; - + it.each([ + [-5, -10], + [5, 0], + [10, 5], + [90, 60], + ])('saturates a value "%s" greater than maxValue', (unsafeInput, expected) => { const mockField = useFormFieldMock(); const wrapper = mount( ); @@ -91,6 +86,24 @@ describe('ScheduleItemField', () => { .last() .simulate('change', { target: { value: unsafeInput } }); - expect(mockField.setValue).toHaveBeenCalledWith('0s'); + expect(mockField.setValue).toHaveBeenCalledWith(`${expected}s`); + }); + + it('skips updating a non-numeric values', () => { + const unsafeInput = 'this is not a number'; + + const mockField = useFormFieldMock(); + const wrapper = mount( + + + + ); + + wrapper + .find('[data-test-subj="interval"]') + .last() + .simulate('change', { target: { value: unsafeInput } }); + + expect(mockField.setValue).not.toHaveBeenCalled(); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation/components/schedule_item_field/schedule_item_field.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation/components/schedule_item_field/schedule_item_field.tsx index 241e3869958a8..2e0f3739ff59a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation/components/schedule_item_field/schedule_item_field.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation/components/schedule_item_field/schedule_item_field.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import type { EuiSelectProps, EuiFieldNumberProps } from '@elastic/eui'; import { EuiFlexGroup, @@ -14,8 +15,6 @@ import { EuiSelect, transparentize, } from '@elastic/eui'; -import { isEmpty } from 'lodash/fp'; -import React, { useCallback, useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; import type { FieldHook } from '../../../../shared_imports'; @@ -27,8 +26,9 @@ interface ScheduleItemProps { field: FieldHook; dataTestSubj: string; idAria: string; - isDisabled: boolean; - minimumValue?: number; + isDisabled?: boolean; + minValue?: number; + maxValue?: number; timeTypes?: string[]; fullWidth?: boolean; } @@ -67,24 +67,16 @@ const MyEuiSelect = styled(EuiSelect)` box-shadow: none; `; -const getNumberFromUserInput = (input: string, minimumValue = 0): number => { - const number = parseInt(input, 10); - if (Number.isNaN(number)) { - return minimumValue; - } else { - return Math.max(minimumValue, Math.min(number, Number.MAX_SAFE_INTEGER)); - } -}; - -export const ScheduleItemField = ({ - dataTestSubj, +export function ScheduleItemField({ field, - idAria, isDisabled, - minimumValue = 0, - timeTypes = ['s', 'm', 'h'], + dataTestSubj, + idAria, + minValue = Number.MIN_SAFE_INTEGER, + maxValue = Number.MAX_SAFE_INTEGER, + timeTypes = DEFAULT_TIME_DURATION_UNITS, fullWidth = false, -}: ScheduleItemProps) => { +}: ScheduleItemProps): JSX.Element { const [timeType, setTimeType] = useState(timeTypes[0]); const [timeVal, setTimeVal] = useState(0); const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(field); @@ -100,38 +92,40 @@ export const ScheduleItemField = ({ const onChangeTimeVal = useCallback>( (e) => { - const sanitizedValue = getNumberFromUserInput(e.target.value, minimumValue); - setTimeVal(sanitizedValue); - setValue(`${sanitizedValue}${timeType}`); + const number = parseInt(e.target.value, 10); + + if (Number.isNaN(number)) { + return; + } + + const newTimeValue = saturate(number, minValue, maxValue); + + setTimeVal(newTimeValue); + setValue(`${newTimeValue}${timeType}`); }, - [minimumValue, setValue, timeType] + [minValue, maxValue, setValue, timeType] ); useEffect(() => { - if (value !== `${timeVal}${timeType}`) { - const filterTimeVal = value.match(/\d+/g); - const filterTimeType = value.match(/[a-zA-Z]+/g); - if ( - !isEmpty(filterTimeVal) && - filterTimeVal != null && - !isNaN(Number(filterTimeVal[0])) && - Number(filterTimeVal[0]) !== Number(timeVal) - ) { - setTimeVal(Number(filterTimeVal[0])); - } - if ( - !isEmpty(filterTimeType) && - filterTimeType != null && - timeTypes.includes(filterTimeType[0]) && - filterTimeType[0] !== timeType - ) { - setTimeType(filterTimeType[0]); - } + if (value === `${timeVal}${timeType}`) { + return; } + + const isNegative = value.startsWith('-'); + const durationRegexp = new RegExp(`^\\-?(\\d+)(${timeTypes.join('|')})$`); + const durationMatchArray = value.match(durationRegexp); + + if (!durationMatchArray) { + return; + } + + const [, timeStr, unit] = durationMatchArray; + const time = parseInt(timeStr, 10) * (isNegative ? -1 : 1); + + setTimeVal(time); + setTimeType(unit); }, [timeType, timeTypes, timeVal, value]); - // EUI missing some props - const rest = { disabled: isDisabled }; const label = useMemo( () => ( @@ -161,21 +155,27 @@ export const ScheduleItemField = ({ timeTypes.includes(type.value))} - onChange={onChangeTimeType} value={timeType} + onChange={onChangeTimeType} + disabled={isDisabled} aria-label={field.label} data-test-subj="timeType" - {...rest} /> } fullWidth - min={minimumValue} - max={Number.MAX_SAFE_INTEGER} - onChange={onChangeTimeVal} + min={minValue} + max={maxValue} value={timeVal} + onChange={onChangeTimeVal} + disabled={isDisabled} data-test-subj="interval" - {...rest} /> ); -}; +} + +const DEFAULT_TIME_DURATION_UNITS = ['s', 'm', 'h']; + +function saturate(input: number, minValue: number, maxValue: number): number { + return Math.max(minValue, Math.min(input, maxValue)); +} diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation/components/step_rule_actions/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation/components/step_rule_actions/index.test.tsx index 583769069157d..d0c1a729d1906 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation/components/step_rule_actions/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation/components/step_rule_actions/index.test.tsx @@ -28,7 +28,7 @@ jest.mock('../../../../common/lib/kibana', () => ({ application: { getUrlForApp: jest.fn(), capabilities: { - siem: { + siemV2: { crud: true, }, actions: { diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.test.tsx index 6a31f9bee8fd7..61ca99a70405a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.test.tsx @@ -45,6 +45,7 @@ import { } from '../../../rule_creation/components/related_integrations/test_helpers'; import { useEsqlAvailability } from '../../../../common/hooks/esql/use_esql_availability'; import { useMLRuleConfig } from '../../../../common/components/ml/hooks/use_ml_rule_config'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; // Set the extended default timeout for all define rule step form test jest.setTimeout(10 * 1000); @@ -207,6 +208,7 @@ jest.mock('../../../../detections/containers/detection_engine/rules/use_rule_fro jest.mock('../../../../common/hooks/esql/use_esql_availability'); jest.mock('../../../../common/components/ml/hooks/use_ml_rule_config'); +jest.mock('../../../../common/components/user_privileges'); const mockUseRuleFromTimeline = useRuleFromTimeline as jest.Mock; const onOpenTimeline = jest.fn(); @@ -226,6 +228,9 @@ describe('StepDefineRule', () => { loading: false, mlSuppressionFields: [], }); + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { read: true }, + }); }); it('renders correctly', () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.tsx index 88423bb64cf05..c5c3f1754b048 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.tsx @@ -93,6 +93,7 @@ import { usePersistentNewTermsState } from './use_persistent_new_terms_state'; import { usePersistentAlertSuppressionState } from './use_persistent_alert_suppression_state'; import { usePersistentThresholdState } from './use_persistent_threshold_state'; import { usePersistentQuery } from './use_persistent_query'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; import { usePersistentMachineLearningState } from './use_persistent_machine_learning_state'; import { usePersistentThreatMatchState } from './use_persistent_threat_match_state'; @@ -191,6 +192,9 @@ const StepDefineRuleComponent: FC = ({ const isThresholdRule = getIsThresholdRule(ruleType); const alertSuppressionUpsellingMessage = useUpsellingMessage('alert_suppression_rule_form'); const { getFields, reset, setFieldValue } = form; + const { + timelinePrivileges: { read: canAttachTimelineTemplates }, + } = useUserPrivileges(); // Callback for when user toggles between Data Views and Index Patterns const onChangeDataSource = useCallback( @@ -700,7 +704,7 @@ const StepDefineRuleComponent: FC = ({ component={PickTimeline} componentProps={{ idAria: 'detectionEngineStepDefineRuleTimeline', - isDisabled: isLoading, + isDisabled: isLoading || !canAttachTimelineTemplates, dataTestSubj: 'detectionEngineStepDefineRuleTimeline', }} /> diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_schedule_rule/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_schedule_rule/index.tsx index 7c309ed32a68b..be50ef8432a48 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_schedule_rule/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_schedule_rule/index.tsx @@ -48,7 +48,7 @@ const StepScheduleRuleComponent: FC = ({ idAria: 'detectionEngineStepScheduleRuleInterval', isDisabled: isLoading, dataTestSubj: 'detectionEngineStepScheduleRuleInterval', - minimumValue: 1, + minValue: 1, }} /> = ({ idAria: 'detectionEngineStepScheduleRuleFrom', isDisabled: isLoading, dataTestSubj: 'detectionEngineStepScheduleRuleFrom', - minimumValue: 1, + minValue: 0, }} /> diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/helpers.test.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/helpers.test.ts index d28634fb6691a..15acb67c63c19 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/helpers.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/helpers.test.ts @@ -27,7 +27,6 @@ import type { } from '../../../../detections/pages/detection_engine/rules/types'; import { AlertSuppressionDurationType } from '../../../../detections/pages/detection_engine/rules/types'; import { - getTimeTypeValue, formatDefineStepData, formatScheduleStepData, formatAboutStepData, @@ -54,56 +53,6 @@ import { } from '../../../rule_creation/components/alert_suppression_edit'; describe('helpers', () => { - describe('getTimeTypeValue', () => { - test('returns timeObj with value 0 if no time value found', () => { - const result = getTimeTypeValue('m'); - - expect(result).toEqual({ unit: 'm', value: 0 }); - }); - - test('returns timeObj with unit set to default unit value of "ms" if no expected time type found', () => { - const result = getTimeTypeValue('5l'); - - expect(result).toEqual({ unit: 'ms', value: 5 }); - }); - - test('returns timeObj with unit of s and value 5 when time is 5s ', () => { - const result = getTimeTypeValue('5s'); - - expect(result).toEqual({ unit: 's', value: 5 }); - }); - - test('returns timeObj with unit of m and value 5 when time is 5m ', () => { - const result = getTimeTypeValue('5m'); - - expect(result).toEqual({ unit: 'm', value: 5 }); - }); - - test('returns timeObj with unit of h and value 5 when time is 5h ', () => { - const result = getTimeTypeValue('5h'); - - expect(result).toEqual({ unit: 'h', value: 5 }); - }); - - test('returns timeObj with value of 5 when time is float like 5.6m ', () => { - const result = getTimeTypeValue('5m'); - - expect(result).toEqual({ unit: 'm', value: 5 }); - }); - - test('returns timeObj with value of 0 and unit of "ms" if random string passed in', () => { - const result = getTimeTypeValue('random'); - - expect(result).toEqual({ unit: 'ms', value: 0 }); - }); - - test('returns timeObj with unit of d and value 5 when time is 5d ', () => { - const result = getTimeTypeValue('5d'); - - expect(result).toEqual({ unit: 'd', value: 5 }); - }); - }); - describe('filterEmptyThreats', () => { let mockThreat: Threat; @@ -639,12 +588,9 @@ describe('helpers', () => { test('returns formatted object as ScheduleStepRuleJson', () => { const result = formatScheduleStepData(mockData); const expected: ScheduleStepRuleJson = { - from: 'now-660s', + from: 'now-11m', to: 'now', interval: '5m', - meta: { - from: '6m', - }, }; expect(result).toEqual(expected); @@ -657,12 +603,9 @@ describe('helpers', () => { delete mockStepData.to; const result = formatScheduleStepData(mockStepData); const expected: ScheduleStepRuleJson = { - from: 'now-660s', + from: 'now-11m', to: 'now', interval: '5m', - meta: { - from: '6m', - }, }; expect(result).toEqual(expected); @@ -675,51 +618,34 @@ describe('helpers', () => { }; const result = formatScheduleStepData(mockStepData); const expected: ScheduleStepRuleJson = { - from: 'now-660s', + from: 'now-11m', to: 'now', interval: '5m', - meta: { - from: '6m', - }, }; expect(result).toEqual(expected); }); - test('returns formatted object if "from" random string', () => { + test('returns unchanged data when "from" is a random string', () => { const mockStepData: ScheduleStepRule = { ...mockData, from: 'random', }; + const result = formatScheduleStepData(mockStepData); - const expected: ScheduleStepRuleJson = { - from: 'now-300s', - to: 'now', - interval: '5m', - meta: { - from: 'random', - }, - }; - expect(result).toEqual(expected); + expect(result).toMatchObject(mockStepData); }); - test('returns formatted object if "interval" random string', () => { + test('returns unchanged data when "interval" is a random string', () => { const mockStepData: ScheduleStepRule = { ...mockData, interval: 'random', }; + const result = formatScheduleStepData(mockStepData); - const expected: ScheduleStepRuleJson = { - from: 'now-360s', - to: 'now', - interval: 'random', - meta: { - from: '6m', - }, - }; - expect(result).toEqual(expected); + expect(result).toMatchObject(mockStepData); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/helpers.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/helpers.ts index 4610e26321797..4872f1ace4936 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/helpers.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/helpers.ts @@ -9,7 +9,6 @@ import { has, isEmpty, get } from 'lodash/fp'; import type { Unit } from '@kbn/datemath'; -import moment from 'moment'; import deepmerge from 'deepmerge'; import omit from 'lodash/omit'; @@ -33,6 +32,7 @@ import type { import type { ActionTypeRegistryContract } from '@kbn/triggers-actions-ui-plugin/public'; +import { TimeDuration } from '@kbn/securitysolution-utils/time_duration'; import { assertUnreachable } from '../../../../../common/utility_types'; import { transformAlertToRuleAction, @@ -570,22 +570,20 @@ export const formatDefineStepData = (defineStepData: DefineStepRule): DefineStep export const formatScheduleStepData = (scheduleData: ScheduleStepRule): ScheduleStepRuleJson => { const { ...formatScheduleData } = scheduleData; - if (!isEmpty(formatScheduleData.interval) && !isEmpty(formatScheduleData.from)) { - const { unit: intervalUnit, value: intervalValue } = getTimeTypeValue( - formatScheduleData.interval - ); - const { unit: fromUnit, value: fromValue } = getTimeTypeValue(formatScheduleData.from); - const duration = moment.duration(intervalValue, intervalUnit); - duration.add(fromValue, fromUnit); - formatScheduleData.from = `now-${duration.asSeconds()}s`; + + const interval = TimeDuration.parse(formatScheduleData.interval ?? ''); + const lookBack = TimeDuration.parse(formatScheduleData.from ?? ''); + + if (interval !== undefined && lookBack !== undefined) { + const fromOffset = TimeDuration.fromMilliseconds( + interval.toMilliseconds() + lookBack.toMilliseconds() + ).toString(); + + formatScheduleData.from = `now-${fromOffset}`; formatScheduleData.to = 'now'; } - return { - ...formatScheduleData, - meta: { - from: scheduleData.from, - }, - }; + + return formatScheduleData; }; export const formatAboutStepData = ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/json_diff/json_diff.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/json_diff/json_diff.test.tsx index 58ee6b56528a5..1c8d7a65fa9d2 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/json_diff/json_diff.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/json_diff/json_diff.test.tsx @@ -28,18 +28,6 @@ function findChildByTextContent(parent: Element, textContent: string): HTMLEleme ) as HTMLElement; } -/* - Finds a diff line element (".diff-line") that contains a particular text content. - Match doesn't have to be exact, it's enough for the line to include the text. -*/ -function findDiffLineContaining(text: string): Element | null { - const foundLine = Array.from(document.querySelectorAll('.diff-line')).find((element) => - (element.textContent || '').includes(text) - ); - - return foundLine || null; -} - describe('Rule upgrade workflow: viewing rule changes in JSON diff view', () => { it.each(['light', 'dark'] as const)( 'User can see precisely how property values would change after upgrade - %s theme', @@ -210,68 +198,6 @@ describe('Rule upgrade workflow: viewing rule changes in JSON diff view', () => ); }); - it('Properties with semantically equal values should not be shown as modified', () => { - const oldRule: RuleResponse = { - ...savedRuleMock, - version: 1, - }; - - const newRule: RuleResponse = { - ...savedRuleMock, - version: 2, - }; - - /* DURATION */ - /* Semantically equal durations should not be shown as modified */ - const { rerender } = render( - - ); - expect(findDiffLineContaining('"from":')).toBeNull(); - - rerender( - - ); - expect(findDiffLineContaining('"from":')).toBeNull(); - - rerender( - - ); - expect(findDiffLineContaining('"from":')).toBeNull(); - - /* Semantically different durations should generate diff */ - rerender( - - ); - expect(findDiffLineContaining('- "from": "now-7260s",+ "from": "now-7200s",')).not.toBeNull(); - - /* NOTE - Investigation guide */ - rerender(); - expect(findDiffLineContaining('"note":')).toBeNull(); - - rerender( - - ); - expect(findDiffLineContaining('"note":')).toBeNull(); - - rerender(); - expect(findDiffLineContaining('"note":')).toBeNull(); - - rerender(); - expect(findDiffLineContaining('- "note": "",+ "note": "abc",')).not.toBeNull(); - }); - it('Unchanged sections of a rule should be hidden by default', async () => { const oldRule: RuleResponse = { ...savedRuleMock, diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/per_field_diff/get_field_diffs_for_grouped_fields.test.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/per_field_diff/get_field_diffs_for_grouped_fields.test.ts new file mode 100644 index 0000000000000..b2a3c6e75cf51 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/per_field_diff/get_field_diffs_for_grouped_fields.test.ts @@ -0,0 +1,392 @@ +/* + * 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 { RuleSchedule } from '../../../../../../common/api/detection_engine/model/rule_schema/rule_schedule'; +import type { ThreeWayDiff } from '../../../../../../common/api/detection_engine'; +import { getFieldDiffsForRuleSchedule } from './get_field_diffs_for_grouped_fields'; + +describe('getFieldDiffsForRuleSchedule', () => { + describe('full rule schedule', () => { + it('returns interval diff', () => { + const result = getFieldDiffsForRuleSchedule({ + current_version: { + interval: '10m', + from: 'now-8m', + to: 'now', + }, + target_version: { + interval: '11m', + from: 'now-8m', + to: 'now', + }, + } as ThreeWayDiff); + + expect(result).toEqual([ + { + fieldName: 'interval', + currentVersion: '10m', + targetVersion: '11m', + }, + ]); + }); + + it('returns from diff', () => { + const result = getFieldDiffsForRuleSchedule({ + current_version: { + interval: '10m', + from: 'now-8m', + to: 'now', + }, + target_version: { + interval: '10m', + from: 'now-7m', + to: 'now', + }, + } as ThreeWayDiff); + + expect(result).toEqual([ + { + fieldName: 'from', + currentVersion: 'now-8m', + targetVersion: 'now-7m', + }, + ]); + }); + + it('returns to diff', () => { + const result = getFieldDiffsForRuleSchedule({ + current_version: { + interval: '10m', + from: 'now-5m', + to: 'now', + }, + target_version: { + interval: '10m', + from: 'now-5m', + to: 'now-2m', + }, + } as ThreeWayDiff); + + expect(result).toEqual([ + { + fieldName: 'to', + currentVersion: 'now', + targetVersion: 'now-2m', + }, + ]); + }); + + it('returns full diff', () => { + const result = getFieldDiffsForRuleSchedule({ + current_version: { + interval: '10m', + from: 'now-5m', + to: 'now', + }, + target_version: { + interval: '11m', + from: 'now-6m', + to: 'now-2m', + }, + } as ThreeWayDiff); + + expect(result).toEqual([ + { + fieldName: 'interval', + currentVersion: '10m', + targetVersion: '11m', + }, + { + fieldName: 'from', + currentVersion: 'now-5m', + targetVersion: 'now-6m', + }, + { + fieldName: 'to', + currentVersion: 'now', + targetVersion: 'now-2m', + }, + ]); + }); + + it('returns full diff when current lookback is negative', () => { + const result = getFieldDiffsForRuleSchedule({ + current_version: { + interval: '10m', + from: 'now-5m', + to: 'now', + }, + target_version: { + interval: '11m', + from: 'now-15m', + to: 'now', + }, + } as ThreeWayDiff); + + expect(result).toEqual([ + { + fieldName: 'interval', + currentVersion: '10m', + targetVersion: '11m', + }, + { + fieldName: 'from', + currentVersion: 'now-5m', + targetVersion: 'now-15m', + }, + ]); + }); + + it('returns full diff when current to is not now', () => { + const result = getFieldDiffsForRuleSchedule({ + current_version: { + interval: '10m', + from: 'now-15m', + to: 'now-2m', + }, + target_version: { + interval: '11m', + from: 'now-15m', + to: 'now', + }, + } as ThreeWayDiff); + + expect(result).toEqual([ + { + fieldName: 'interval', + currentVersion: '10m', + targetVersion: '11m', + }, + { + fieldName: 'to', + currentVersion: 'now-2m', + targetVersion: 'now', + }, + ]); + }); + + it('returns full diff when target lookback is negative', () => { + const result = getFieldDiffsForRuleSchedule({ + current_version: { + interval: '10m', + from: 'now-15m', + to: 'now', + }, + target_version: { + interval: '11m', + from: 'now-5m', + to: 'now', + }, + } as ThreeWayDiff); + + expect(result).toEqual([ + { + fieldName: 'interval', + currentVersion: '10m', + targetVersion: '11m', + }, + { + fieldName: 'from', + currentVersion: 'now-15m', + targetVersion: 'now-5m', + }, + ]); + }); + + it('returns full diff when target to is not now', () => { + const result = getFieldDiffsForRuleSchedule({ + current_version: { + interval: '10m', + from: 'now-15m', + to: 'now', + }, + target_version: { + interval: '11m', + from: 'now-15m', + to: 'now-2m', + }, + } as ThreeWayDiff); + + expect(result).toEqual([ + { + fieldName: 'interval', + currentVersion: '10m', + targetVersion: '11m', + }, + { + fieldName: 'to', + currentVersion: 'now', + targetVersion: 'now-2m', + }, + ]); + }); + + it('returns diff with current undefined', () => { + const result = getFieldDiffsForRuleSchedule({ + current_version: undefined, + target_version: { + interval: '11m', + from: 'now-8m', + to: 'now', + }, + } as ThreeWayDiff); + + expect(result).toEqual([ + { + fieldName: 'interval', + currentVersion: '', + targetVersion: '11m', + }, + { + fieldName: 'from', + currentVersion: '', + targetVersion: 'now-8m', + }, + { + fieldName: 'to', + currentVersion: '', + targetVersion: 'now', + }, + ]); + }); + + it('returns diff with target undefined', () => { + const result = getFieldDiffsForRuleSchedule({ + current_version: { + interval: '11m', + from: 'now-8m', + to: 'now', + }, + target_version: undefined, + } as ThreeWayDiff); + + expect(result).toEqual([ + { + fieldName: 'interval', + currentVersion: '11m', + targetVersion: '', + }, + { + fieldName: 'from', + currentVersion: 'now-8m', + targetVersion: '', + }, + { + fieldName: 'to', + currentVersion: 'now', + targetVersion: '', + }, + ]); + }); + }); + + describe('simple rule schedule', () => { + it('returns diff', () => { + const result = getFieldDiffsForRuleSchedule({ + current_version: { + interval: '10m', + from: 'now-11m', + to: 'now', + }, + target_version: { + interval: '11m', + from: 'now-11m', + to: 'now', + }, + } as ThreeWayDiff); + + expect(result).toEqual([ + { + fieldName: 'interval', + currentVersion: '10m', + targetVersion: '11m', + }, + { + fieldName: 'lookback', + currentVersion: '1m', + targetVersion: '0s', + }, + ]); + }); + + it('returns diff when current is undefined', () => { + const result = getFieldDiffsForRuleSchedule({ + current_version: undefined, + target_version: { + interval: '11m', + from: 'now-11m', + to: 'now', + }, + } as ThreeWayDiff); + + expect(result).toEqual([ + { + fieldName: 'interval', + currentVersion: '', + targetVersion: '11m', + }, + { + fieldName: 'lookback', + currentVersion: '', + targetVersion: '0s', + }, + ]); + }); + + it('returns diff when target is undefined', () => { + const result = getFieldDiffsForRuleSchedule({ + current_version: { + interval: '10m', + from: 'now-11m', + to: 'now', + }, + target_version: undefined, + } as ThreeWayDiff); + + expect(result).toEqual([ + { + fieldName: 'interval', + currentVersion: '10m', + targetVersion: '', + }, + { + fieldName: 'lookback', + currentVersion: '1m', + targetVersion: '', + }, + ]); + }); + }); + + describe('no diff', () => { + it('returns empty array for equal versions', () => { + const result = getFieldDiffsForRuleSchedule({ + current_version: { + interval: '10m', + from: 'now-15m', + to: 'now', + }, + target_version: { + interval: '10m', + from: 'now-15m', + to: 'now', + }, + } as ThreeWayDiff); + + expect(result).toEqual([]); + }); + + it('returns empty array for undefined versions', () => { + const result = getFieldDiffsForRuleSchedule({ + current_version: undefined, + target_version: undefined, + } as ThreeWayDiff); + + expect(result).toEqual([]); + }); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/per_field_diff/get_field_diffs_for_grouped_fields.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/per_field_diff/get_field_diffs_for_grouped_fields.ts index 21717998483ea..7dffd3a593b15 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/per_field_diff/get_field_diffs_for_grouped_fields.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/per_field_diff/get_field_diffs_for_grouped_fields.ts @@ -6,12 +6,18 @@ */ import stringify from 'json-stable-stringify'; +import type { + RuleSchedule, + SimpleRuleSchedule, +} from '../../../../../../common/api/detection_engine/model/rule_schema/rule_schedule'; +import { toSimpleRuleSchedule } from '../../../../../../common/api/detection_engine/model/rule_schema/to_simple_rule_schedule'; import type { AllFieldsDiff, RuleFieldsDiffWithDataSource, RuleFieldsDiffWithEqlQuery, RuleFieldsDiffWithEsqlQuery, RuleFieldsDiffWithKqlQuery, + ThreeWayDiff, } from '../../../../../../common/api/detection_engine'; import type { FieldDiff } from '../../../model/rule_details/rule_field_diff'; @@ -277,34 +283,75 @@ export const getFieldDiffsForThreatQuery = ( }; export const getFieldDiffsForRuleSchedule = ( - ruleScheduleThreeWayDiff: AllFieldsDiff['rule_schedule'] + ruleScheduleThreeWayDiff: ThreeWayDiff ): FieldDiff[] => { - return [ - ...(ruleScheduleThreeWayDiff.current_version?.interval !== - ruleScheduleThreeWayDiff.target_version?.interval - ? [ - { - fieldName: 'interval', - currentVersion: sortAndStringifyJson( - ruleScheduleThreeWayDiff.current_version?.interval - ), - targetVersion: sortAndStringifyJson(ruleScheduleThreeWayDiff.target_version?.interval), - }, - ] - : []), - ...(ruleScheduleThreeWayDiff.current_version?.lookback !== - ruleScheduleThreeWayDiff.target_version?.lookback - ? [ - { - fieldName: 'lookback', - currentVersion: sortAndStringifyJson( - ruleScheduleThreeWayDiff.current_version?.lookback - ), - targetVersion: sortAndStringifyJson(ruleScheduleThreeWayDiff.target_version?.lookback), - }, - ] - : []), - ]; + const fieldsDiff: FieldDiff[] = []; + + const current = ruleScheduleThreeWayDiff.current_version; + const target = ruleScheduleThreeWayDiff.target_version; + + const currentSimpleRuleSchedule = current ? toSimpleRuleSchedule(current) : undefined; + const targetSimpleRuleSchedule = target ? toSimpleRuleSchedule(target) : undefined; + + const isCurrentSimpleRuleScheduleValid = !current || (current && currentSimpleRuleSchedule); + const isTargetSimpleRuleScheduleValid = !target || (target && targetSimpleRuleSchedule); + + // Show simple rule schedule diff only when current and target versions are convertable + // to simple rule schedule or one of the versions is undefined. + if (isCurrentSimpleRuleScheduleValid && isTargetSimpleRuleScheduleValid) { + return getFieldDiffsForSimpleRuleSchedule(currentSimpleRuleSchedule, targetSimpleRuleSchedule); + } + + if (current?.interval !== target?.interval) { + fieldsDiff.push({ + fieldName: 'interval', + currentVersion: sortAndStringifyJson(current?.interval), + targetVersion: sortAndStringifyJson(target?.interval), + }); + } + + if (current?.from !== target?.from) { + fieldsDiff.push({ + fieldName: 'from', + currentVersion: sortAndStringifyJson(current?.from), + targetVersion: sortAndStringifyJson(target?.from), + }); + } + + if (current?.to !== target?.to) { + fieldsDiff.push({ + fieldName: 'to', + currentVersion: sortAndStringifyJson(current?.to), + targetVersion: sortAndStringifyJson(target?.to), + }); + } + + return fieldsDiff; +}; + +const getFieldDiffsForSimpleRuleSchedule = ( + current: SimpleRuleSchedule | undefined, + target: SimpleRuleSchedule | undefined +): FieldDiff[] => { + const fieldsDiff: FieldDiff[] = []; + + if (current?.interval !== target?.interval) { + fieldsDiff.push({ + fieldName: 'interval', + currentVersion: sortAndStringifyJson(current?.interval), + targetVersion: sortAndStringifyJson(target?.interval), + }); + } + + if (current?.lookback !== target?.lookback) { + fieldsDiff.push({ + fieldName: 'lookback', + currentVersion: sortAndStringifyJson(current?.lookback), + targetVersion: sortAndStringifyJson(target?.lookback), + }); + } + + return fieldsDiff; }; export const getFieldDiffsForRuleNameOverride = ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab.tsx index c2bf9ffa29098..010c7e4aa4ad4 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab.tsx @@ -18,14 +18,10 @@ import { } from '@elastic/eui'; import type { Filter } from '@kbn/es-query'; import { normalizeMachineLearningJobIds } from '../../../../../common/detection_engine/utils'; -import { - formatScheduleStepData, - filterEmptyThreats, -} from '../../../rule_creation_ui/pages/rule_creation/helpers'; +import { filterEmptyThreats } from '../../../rule_creation_ui/pages/rule_creation/helpers'; import type { RuleResponse } from '../../../../../common/api/detection_engine/model/rule_schema/rule_schemas.gen'; import { DiffView } from './json_diff/diff_view'; import * as i18n from './json_diff/translations'; -import { getHumanizedDuration } from '../../../../detections/pages/detection_engine/rules/helpers'; /* Inclding these properties in diff display might be confusing to users. */ const HIDDEN_PROPERTIES: Array = [ @@ -79,20 +75,6 @@ const sortAndStringifyJson = (jsObject: Record): string => const normalizeRule = (originalRule: RuleResponse): RuleResponse => { const rule = { ...originalRule }; - /* - Convert the "from" property value to a humanized duration string, like 'now-1m' or 'now-2h'. - Conversion is needed to skip showing the diff for the "from" property when the same - duration is represented in different time units. For instance, 'now-1h' and 'now-3600s' - indicate a one-hour duration. - The same helper is used in the rule editing UI to format "from" before submitting the edits. - So, after the rule is saved, the "from" property unit/value might differ from what's in the package. - */ - rule.from = formatScheduleStepData({ - interval: rule.interval, - from: getHumanizedDuration(rule.from, rule.interval), - to: rule.to, - }).from; - /* Default "note" to an empty string if it's not present. Sometimes, in a new version of a rule, the "note" value equals an empty string, while diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_schedule_section.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_schedule_section.tsx index 5ed99e4328136..45b7eb3f5ecf0 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_schedule_section.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_schedule_section.tsx @@ -8,9 +8,10 @@ import React from 'react'; import { EuiDescriptionList, EuiText } from '@elastic/eui'; import type { EuiDescriptionListProps } from '@elastic/eui'; +import { normalizeDateMath } from '@kbn/securitysolution-utils/date_math'; +import { toSimpleRuleSchedule } from '../../../../../common/api/detection_engine/model/rule_schema/to_simple_rule_schedule'; import { IntervalAbbrScreenReader } from '../../../../common/components/accessibility'; import type { RuleResponse } from '../../../../../common/api/detection_engine/model/rule_schema'; -import { getHumanizedDuration } from '../../../../detections/pages/detection_engine/rules/helpers'; import { DEFAULT_DESCRIPTION_LIST_COLUMN_WIDTHS } from './constants'; import * as i18n from './translations'; @@ -36,16 +37,12 @@ const Interval = ({ interval }: IntervalProps) => ( ); -interface FromProps { - from: string; - interval: string; +interface LookBackProps { + value: string; } -const From = ({ from, interval }: FromProps) => ( - +const LookBack = ({ value }: LookBackProps) => ( + ); export interface RuleScheduleSectionProps extends React.ComponentProps { @@ -62,18 +59,46 @@ export const RuleScheduleSection = ({ return null; } - const ruleSectionListItems = []; + const to = rule.to ?? 'now'; - ruleSectionListItems.push( - { - title: {i18n.INTERVAL_FIELD_LABEL}, - description: , - }, - { - title: {i18n.FROM_FIELD_LABEL}, - description: , - } - ); + const simpleRuleSchedule = toSimpleRuleSchedule({ + interval: rule.interval, + from: rule.from, + to, + }); + + const ruleSectionListItems = !simpleRuleSchedule + ? [ + { + title: {i18n.INTERVAL_FIELD_LABEL}, + description: , + }, + { + title: ( + + {i18n.RULE_SOURCE_EVENTS_TIME_RANGE_FIELD_LABEL} + + ), + description: ( + + {i18n.RULE_SOURCE_EVENTS_TIME_RANGE( + normalizeDateMath(rule.from), + normalizeDateMath(to) + )} + + ), + }, + ] + : [ + { + title: {i18n.INTERVAL_FIELD_LABEL}, + description: , + }, + { + title: {i18n.LOOK_BACK_FIELD_LABEL}, + description: , + }, + ]; return (
diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/get_subfield_changes/rule_schedule.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/get_subfield_changes/rule_schedule.ts index 8bbf0c9235257..2f15eff892752 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/get_subfield_changes/rule_schedule.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/get_subfield_changes/rule_schedule.ts @@ -5,14 +5,23 @@ * 2.0. */ +import type { SimpleRuleSchedule } from '../../../../../../../../common/api/detection_engine/model/rule_schema/rule_schedule'; +import { toSimpleRuleSchedule } from '../../../../../../../../common/api/detection_engine/model/rule_schema/to_simple_rule_schedule'; import { stringifyToSortedJson } from '../utils'; import type { DiffableAllFields } from '../../../../../../../../common/api/detection_engine'; import type { SubfieldChange } from '../types'; -export const getSubfieldChangesForRuleSchedule = ( +export function getSubfieldChangesForRuleSchedule( oldFieldValue?: DiffableAllFields['rule_schedule'], newFieldValue?: DiffableAllFields['rule_schedule'] -): SubfieldChange[] => { +): SubfieldChange[] { + const oldSimpleRuleSchedule = oldFieldValue ? toSimpleRuleSchedule(oldFieldValue) : undefined; + const newSimpleRuleSchedule = newFieldValue ? toSimpleRuleSchedule(newFieldValue) : undefined; + + if (oldSimpleRuleSchedule && newSimpleRuleSchedule) { + return getSubfieldChangesForSimpleRuleSchedule(oldSimpleRuleSchedule, newSimpleRuleSchedule); + } + const changes: SubfieldChange[] = []; if (oldFieldValue?.interval !== newFieldValue?.interval) { @@ -23,13 +32,46 @@ export const getSubfieldChangesForRuleSchedule = ( }); } - if (oldFieldValue?.lookback !== newFieldValue?.lookback) { + if (oldFieldValue?.from !== newFieldValue?.from) { + changes.push({ + subfieldName: 'from', + oldSubfieldValue: stringifyToSortedJson(oldFieldValue?.from), + newSubfieldValue: stringifyToSortedJson(newFieldValue?.from), + }); + } + + if (oldFieldValue?.to !== newFieldValue?.to) { + changes.push({ + subfieldName: 'to', + oldSubfieldValue: stringifyToSortedJson(oldFieldValue?.to), + newSubfieldValue: stringifyToSortedJson(newFieldValue?.to), + }); + } + + return changes; +} + +function getSubfieldChangesForSimpleRuleSchedule( + oldFieldValue: SimpleRuleSchedule, + newFieldValue: SimpleRuleSchedule +): SubfieldChange[] { + const changes: SubfieldChange[] = []; + + if (oldFieldValue.interval !== newFieldValue.interval) { + changes.push({ + subfieldName: 'interval', + oldSubfieldValue: stringifyToSortedJson(oldFieldValue?.interval), + newSubfieldValue: stringifyToSortedJson(newFieldValue?.interval), + }); + } + + if (oldFieldValue.lookback !== newFieldValue.lookback) { changes.push({ subfieldName: 'lookback', - oldSubfieldValue: stringifyToSortedJson(oldFieldValue?.lookback), - newSubfieldValue: stringifyToSortedJson(newFieldValue?.lookback), + oldSubfieldValue: stringifyToSortedJson(oldFieldValue.lookback), + newSubfieldValue: stringifyToSortedJson(newFieldValue.lookback), }); } return changes; -}; +} diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/common_rule_field_edit.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/common_rule_field_edit.tsx index 0b8668e90a903..31752fd15b4c5 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/common_rule_field_edit.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/common_rule_field_edit.tsx @@ -65,12 +65,6 @@ import { ruleNameOverrideSerializer, ruleNameOverrideSchema, } from './fields/rule_name_override'; -import { - RuleScheduleEdit, - ruleScheduleSchema, - ruleScheduleDeserializer, - ruleScheduleSerializer, -} from './fields/rule_schedule'; import { SetupEdit, setupSchema } from './fields/setup'; import { SeverityEdit } from './fields/severity'; import { @@ -92,6 +86,7 @@ import { timestampOverrideSerializer, timestampOverrideSchema, } from './fields/timestamp_override'; +import { RuleScheduleForm } from './fields/rule_schedule'; interface CommonRuleFieldEditProps { fieldName: UpgradeableCommonFields; @@ -200,14 +195,7 @@ export function CommonRuleFieldEdit({ fieldName }: CommonRuleFieldEditProps) { /> ); case 'rule_schedule': - return ( - - ); + return ; case 'setup': return ; case 'severity': diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule.tsx deleted file mode 100644 index 3acd7c3050fbb..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule.tsx +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { parseDuration } from '@kbn/alerting-plugin/common'; -import { type FormSchema, type FormData, UseField } from '../../../../../../../shared_imports'; -import { schema } from '../../../../../../rule_creation_ui/components/step_schedule_rule/schema'; -import type { RuleSchedule } from '../../../../../../../../common/api/detection_engine'; -import { secondsToDurationString } from '../../../../../../../detections/pages/detection_engine/rules/helpers'; -import { ScheduleItemField } from '../../../../../../rule_creation/components/schedule_item_field'; - -export const ruleScheduleSchema = { - interval: schema.interval, - from: schema.from, -} as FormSchema<{ - interval: string; - from: string; -}>; - -const componentProps = { - minimumValue: 1, -}; - -export function RuleScheduleEdit(): JSX.Element { - return ( - <> - - - - ); -} - -export function ruleScheduleDeserializer(defaultValue: FormData) { - const lookbackSeconds = parseDuration(defaultValue.rule_schedule.lookback) / 1000; - const lookbackHumanized = secondsToDurationString(lookbackSeconds); - - return { - interval: defaultValue.rule_schedule.interval, - from: lookbackHumanized, - }; -} - -export function ruleScheduleSerializer(formData: FormData): { - rule_schedule: RuleSchedule; -} { - return { - rule_schedule: { - interval: formData.interval, - lookback: formData.from, - }, - }; -} diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/full_rule_schedule_adapter.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/full_rule_schedule_adapter.tsx new file mode 100644 index 0000000000000..38e86651111c7 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/full_rule_schedule_adapter.tsx @@ -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 React from 'react'; +import { TextField } from '@kbn/es-ui-shared-plugin/static/forms/components'; +import type { FieldConfig } from '../../../../../../../../shared_imports'; +import { UseField } from '../../../../../../../../shared_imports'; +import { ScheduleItemField } from '../../../../../../../rule_creation/components/schedule_item_field'; +import * as i18n from './translations'; +import { dateMathValidator } from './validators/date_math_validator'; + +export function FullRuleScheduleAdapter(): JSX.Element { + return ( + <> + + + + + ); +} + +const INTERVAL_COMPONENT_PROPS = { + minValue: 1, +}; + +const INTERVAL_FIELD_CONFIG: FieldConfig = { + label: i18n.INTERVAL_FIELD_LABEL, + helpText: i18n.INTERVAL_FIELD_HELP_TEXT, +}; + +const FROM_FIELD_CONFIG: FieldConfig = { + label: i18n.FROM_FIELD_LABEL, + helpText: i18n.DATE_MATH_HELP_TEXT, + validations: [ + { + validator: dateMathValidator, + }, + ], +}; + +const TO_FIELD_CONFIG: FieldConfig = { + label: i18n.TO_FIELD_LABEL, + helpText: i18n.DATE_MATH_HELP_TEXT, + validations: [ + { + validator: dateMathValidator, + }, + ], +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/full_rule_schedule_form.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/full_rule_schedule_form.tsx new file mode 100644 index 0000000000000..4b42c99fc40bb --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/full_rule_schedule_form.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 React from 'react'; +import type { RuleSchedule } from '../../../../../../../../../common/api/detection_engine/model/rule_schema/rule_schedule'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { type FormData } from '../../../../../../../../shared_imports'; +import { RuleFieldEditFormWrapper } from '../../../field_final_side'; +import { FullRuleScheduleAdapter } from './full_rule_schedule_adapter'; + +export function FullRuleScheduleForm(): JSX.Element { + return ( + + ); +} + +function deserializer(_: unknown, finalRule: DiffableRule): RuleSchedule { + return { + interval: finalRule.rule_schedule.interval, + from: finalRule.rule_schedule.from, + to: finalRule.rule_schedule.to, + }; +} + +function serializer(formData: FormData): { + rule_schedule: RuleSchedule; +} { + return { + rule_schedule: { + interval: formData.interval, + from: formData.from, + to: formData.to, + }, + }; +} diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/index.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/index.ts new file mode 100644 index 0000000000000..ce1f82adc599e --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './rule_schedule_form'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/rule_schedule_form.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/rule_schedule_form.tsx new file mode 100644 index 0000000000000..ca9cb0db316f1 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/rule_schedule_form.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 React, { useMemo } from 'react'; +import { type RuleSchedule } from '../../../../../../../../../common/api/detection_engine/model/rule_schema/rule_schedule'; +import { toSimpleRuleSchedule } from '../../../../../../../../../common/api/detection_engine/model/rule_schema/to_simple_rule_schedule'; +import { SimpleRuleScheduleForm } from './simple_rule_schedule_form'; +import { useFieldUpgradeContext } from '../../../rule_upgrade/field_upgrade_context'; +import { FullRuleScheduleForm } from './full_rule_schedule_form'; + +export function RuleScheduleForm(): JSX.Element { + const { fieldName, finalDiffableRule } = useFieldUpgradeContext(); + const canBeSimplified = useMemo( + () => Boolean(toSimpleRuleSchedule(finalDiffableRule[fieldName] as RuleSchedule)), + [fieldName, finalDiffableRule] + ); + + return canBeSimplified ? : ; +} diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/simple_rule_schedule_adapter.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/simple_rule_schedule_adapter.tsx new file mode 100644 index 0000000000000..a7bc6425f3845 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/simple_rule_schedule_adapter.tsx @@ -0,0 +1,49 @@ +/* + * 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 type { FieldConfig } from '../../../../../../../../shared_imports'; +import { UseField } from '../../../../../../../../shared_imports'; +import { ScheduleItemField } from '../../../../../../../rule_creation/components/schedule_item_field'; +import * as i18n from './translations'; + +export function SimpleRuleScheduleAdapter(): JSX.Element { + return ( + <> + + + + ); +} + +const INTERVAL_COMPONENT_PROPS = { + minValue: 1, +}; + +const LOOKBACK_COMPONENT_PROPS = { + minValue: 0, +}; + +const INTERVAL_FIELD_CONFIG: FieldConfig = { + label: i18n.INTERVAL_FIELD_LABEL, + helpText: i18n.INTERVAL_FIELD_HELP_TEXT, +}; + +const LOOK_BACK_FIELD_CONFIG: FieldConfig = { + label: i18n.LOOK_BACK_FIELD_LABEL, + helpText: i18n.LOOK_BACK_FIELD_HELP_TEXT, +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/simple_rule_schedule_form.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/simple_rule_schedule_form.tsx new file mode 100644 index 0000000000000..28f995dd9afde --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/simple_rule_schedule_form.tsx @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { TimeDuration } from '@kbn/securitysolution-utils/time_duration'; +import type { + RuleSchedule, + SimpleRuleSchedule, +} from '../../../../../../../../../common/api/detection_engine/model/rule_schema/rule_schedule'; +import { toSimpleRuleSchedule } from '../../../../../../../../../common/api/detection_engine/model/rule_schema/to_simple_rule_schedule'; +import { type FormData } from '../../../../../../../../shared_imports'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { RuleFieldEditFormWrapper } from '../../../field_final_side'; +import { SimpleRuleScheduleAdapter } from './simple_rule_schedule_adapter'; +import { invariant } from '../../../../../../../../../common/utils/invariant'; + +export function SimpleRuleScheduleForm(): JSX.Element { + return ( + + ); +} + +function deserializer(_: unknown, finalRule: DiffableRule): Partial { + const simpleRuleSchedule = toSimpleRuleSchedule(finalRule.rule_schedule); + + invariant(simpleRuleSchedule, 'Unable to calculate simple rule schedule'); + + return { + interval: simpleRuleSchedule.interval, + lookback: simpleRuleSchedule.lookback, + }; +} + +function serializer(formData: FormData): { + rule_schedule: RuleSchedule; +} { + const interval = TimeDuration.parse(formData.interval); + const lookBack = TimeDuration.parse(formData.lookback); + + invariant(interval !== undefined && interval.value > 0, 'Rule interval is invalid'); + invariant(lookBack !== undefined && lookBack.value >= 0, "Rule's look-back is invalid"); + + const fromOffsetMs = interval.toMilliseconds() + lookBack.toMilliseconds(); + const fromOffset = TimeDuration.fromMilliseconds(fromOffsetMs); + + const from = `now-${fromOffset}`; + + return { + rule_schedule: { + interval: formData.interval, + from, + to: 'now', + }, + }; +} diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/translations.ts new file mode 100644 index 0000000000000..e7616e54c040e --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/translations.ts @@ -0,0 +1,57 @@ +/* + * 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 INTERVAL_FIELD_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleManagement.fields.interval.label', + { + defaultMessage: 'Runs every', + } +); + +export const INTERVAL_FIELD_HELP_TEXT = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleManagement.fields.interval.helpText', + { + defaultMessage: 'Rules run periodically and detect alerts within the specified time frame.', + } +); + +export const LOOK_BACK_FIELD_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleManagement.fields.lookback.label', + { + defaultMessage: 'Additional look-back time', + } +); + +export const LOOK_BACK_FIELD_HELP_TEXT = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleManagement.fields.lookback.helpText', + { + defaultMessage: 'Adds time to the look-back period to prevent missed alerts.', + } +); + +export const FROM_FIELD_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleManagement.fields.from.label', + { + defaultMessage: 'From', + } +); + +export const TO_FIELD_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleManagement.fields.to.label', + { + defaultMessage: 'To', + } +); + +export const DATE_MATH_HELP_TEXT = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleManagement.fields.from.helpText', + { + defaultMessage: 'Date math expression, e.g. "now", "now-3d", "now+2m".', + } +); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/validators/date_math_validator.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/validators/date_math_validator.ts new file mode 100644 index 0000000000000..944fa99e53de8 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/validators/date_math_validator.ts @@ -0,0 +1,18 @@ +/* + * 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 dateMath from '@kbn/datemath'; +import { type FormData, type ValidationFunc } from '../../../../../../../../../shared_imports'; +import * as i18n from './translations'; + +export const dateMathValidator: ValidationFunc = (data) => { + const { path, value } = data; + + if (!dateMath.parse(value)) { + return { code: 'ERR_DATE_MATH_INVALID', path, message: i18n.INVALID_DATE_MATH }; + } +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/threat_intelligence/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/validators/translations.ts similarity index 57% rename from x-pack/solutions/security/plugins/security_solution/public/threat_intelligence/translations.ts rename to x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/validators/translations.ts index 02553c2c5140a..7e6d2407b9a36 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/threat_intelligence/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/rule_schedule/validators/translations.ts @@ -7,9 +7,9 @@ import { i18n } from '@kbn/i18n'; -export const ACTION_INVESTIGATE_IN_TIMELINE = i18n.translate( - 'xpack.securitySolution.threatIntelligence.investigateInTimelineTitle', +export const INVALID_DATE_MATH = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleManagement.validation.dateMath.invalid', { - defaultMessage: 'Investigate in timeline', + defaultMessage: 'Date math is invalid. Valid examples: "now", "now-3h", "now+2m".', } ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.stories.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.stories.tsx index a49735a35b5be..93dc9c70cf5c8 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.stories.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.stories.tsx @@ -17,7 +17,8 @@ export const Default = () => ( ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.tsx index 24d0e5d6e05f1..e9ee329cfe1be 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.tsx @@ -5,21 +5,36 @@ * 2.0. */ -import React from 'react'; +import React, { useMemo } from 'react'; import { EuiDescriptionList } from '@elastic/eui'; -import { parseDuration } from '@kbn/alerting-plugin/common'; +import type { RuleSchedule } from '../../../../../../../../../common/api/detection_engine/model/rule_schema/rule_schedule'; +import { toSimpleRuleSchedule } from '../../../../../../../../../common/api/detection_engine/model/rule_schema/to_simple_rule_schedule'; import * as i18n from '../../../../translations'; -import type { RuleSchedule } from '../../../../../../../../../common/api/detection_engine'; import { AccessibleTimeValue } from '../../../../rule_schedule_section'; -import { secondsToDurationString } from '../../../../../../../../detections/pages/detection_engine/rules/helpers'; interface RuleScheduleReadOnlyProps { ruleSchedule: RuleSchedule; } export function RuleScheduleReadOnly({ ruleSchedule }: RuleScheduleReadOnlyProps) { - const lookbackSeconds = parseDuration(ruleSchedule.lookback) / 1000; - const lookbackHumanized = secondsToDurationString(lookbackSeconds); + const simpleRuleSchedule = useMemo(() => toSimpleRuleSchedule(ruleSchedule), [ruleSchedule]); + + if (simpleRuleSchedule) { + return ( + , + }, + { + title: i18n.LOOK_BACK_FIELD_LABEL, + description: , + }, + ]} + /> + ); + } return ( , }, { - title: i18n.FROM_FIELD_LABEL, - description: , + title: i18n.RULE_SOURCE_EVENTS_TIME_RANGE_FIELD_LABEL, + description: ( + {i18n.RULE_SOURCE_EVENTS_TIME_RANGE(ruleSchedule.from, ruleSchedule.to)} + ), }, ]} /> diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/mocks.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/mocks.ts index 18973df5ca545..4d0bcbba3041c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/mocks.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/mocks.ts @@ -139,7 +139,8 @@ const commonDiffableRuleFields: DiffableCommonFields = { required_fields: [], rule_schedule: { interval: '5m', - lookback: '360s', + from: 'now-660s', + to: 'now', }, max_signals: DEFAULT_MAX_SIGNALS, }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/translations.tsx similarity index 94% rename from x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/translations.ts rename to x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/translations.tsx index 3f787b60fa427..69e113b5e112c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/translations.tsx @@ -5,7 +5,9 @@ * 2.0. */ +import React from 'react'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; export const RULE_DETAILS_FLYOUT_LABEL = i18n.translate( 'xpack.securitySolution.detectionEngine.ruleDetails.label', @@ -386,13 +388,31 @@ export const INTERVAL_FIELD_LABEL = i18n.translate( } ); -export const FROM_FIELD_LABEL = i18n.translate( - 'xpack.securitySolution.detectionEngine.ruleDetails.fromFieldLabel', +export const LOOK_BACK_FIELD_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDetails.lookBackFieldLabel', { defaultMessage: 'Additional look-back time', } ); +export const RULE_SOURCE_EVENTS_TIME_RANGE_FIELD_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDetails.ruleSourceEventsTimeRangeFieldLabel', + { + defaultMessage: 'Analyzed time range', + } +); + +export const RULE_SOURCE_EVENTS_TIME_RANGE = (from: string, to: string) => ( + {from}, + to: {to}, + }} + /> +); + export const MAX_SIGNALS_FIELD_LABEL = i18n.translate( 'xpack.securitySolution.detectionEngine.ruleDetails.maxAlertsFieldLabel', { diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/forms/schedule_form.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/forms/schedule_form.tsx index 518c18a59a413..4045d9a7e7878 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/forms/schedule_form.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/forms/schedule_form.tsx @@ -84,7 +84,7 @@ export const ScheduleForm = ({ rulesCount, onClose, onConfirm }: ScheduleFormCom idAria: 'bulkEditRulesScheduleIntervalSelector', dataTestSubj: 'bulkEditRulesScheduleIntervalSelector', fullWidth: true, - minimumValue: 1, + minValue: 1, }} /> diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/use_bulk_actions.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/use_bulk_actions.tsx index 0326f5d3f1e5d..2de25b7d30a25 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/use_bulk_actions.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/use_bulk_actions.tsx @@ -14,6 +14,7 @@ import React, { useCallback } from 'react'; import { MAX_MANUAL_RULE_RUN_BULK_SIZE } from '../../../../../../common/constants'; import type { TimeRange } from '../../../../rule_gaps/types'; import { useKibana } from '../../../../../common/lib/kibana'; +import { useUserPrivileges } from '../../../../../common/components/user_privileges'; import { convertRulesFilterToKQL } from '../../../../../../common/detection_engine/rule_management/rule_filtering'; import { DuplicateOptions } from '../../../../../../common/detection_engine/rule_management/constants'; import type { @@ -82,6 +83,9 @@ export const useBulkActions = ({ const { executeBulkAction } = useExecuteBulkAction(); const { bulkExport } = useBulkExport(); const downloadExportedRules = useDownloadExportedRules(); + const { + timelinePrivileges: { crud: canCreateTimelines }, + } = useUserPrivileges(); const { state: { isAllSelected, rules, loadingRuleIds, selectedRuleIds }, @@ -430,7 +434,7 @@ export const useBulkActions = ({ key: i18n.BULK_ACTION_APPLY_TIMELINE_TEMPLATE, name: i18n.BULK_ACTION_APPLY_TIMELINE_TEMPLATE, 'data-test-subj': 'applyTimelineTemplateBulk', - disabled: isEditDisabled, + disabled: !canCreateTimelines || isEditDisabled, onClick: handleBulkEdit(BulkActionEditTypeEnum.set_timeline), toolTipContent: missingActionPrivileges ? i18n.LACK_OF_KIBANA_ACTIONS_FEATURE_PRIVILEGES @@ -592,6 +596,7 @@ export const useBulkActions = ({ filterOptions, completeBulkEditForm, startServices, + canCreateTimelines, ] ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/default_config.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/default_config.test.tsx index 1d722391ba12b..8643504bf9f6f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/default_config.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/default_config.test.tsx @@ -79,6 +79,11 @@ const platinumBaseColumns = [ id: 'user.risk.calculated_level', displayAsText: 'User Risk Level', }, + { + columnHeaderType: 'not-filtered', + id: 'service.risk.calculated_level', + displayAsText: 'Service Risk Level', + }, { columnHeaderType: 'not-filtered', id: 'host.asset.criticality', @@ -89,6 +94,11 @@ const platinumBaseColumns = [ id: 'user.asset.criticality', displayAsText: 'User Criticality', }, + { + columnHeaderType: 'not-filtered', + id: 'service.asset.criticality', + displayAsText: 'Service Criticality', + }, { columnHeaderType: 'not-filtered', id: 'process.name' }, { columnHeaderType: 'not-filtered', id: 'file.name' }, { columnHeaderType: 'not-filtered', id: 'source.ip' }, diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.test.tsx index fa14fc317a78a..e51dcb6f57cde 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.test.tsx @@ -76,7 +76,7 @@ jest.mock('../../../../common/lib/kibana', () => { services: { timelines: { ...mockTimelines }, application: { - capabilities: { siem: { crud_alerts: true, read_alerts: true } }, + capabilities: { siemV2: { crud_alerts: true, read_alerts: true } }, }, cases: { ...mockCasesContract(), diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_timeline_action.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_timeline_action.test.tsx index 7173670f80a68..ab728622c65e9 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_timeline_action.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_timeline_action.test.tsx @@ -13,6 +13,7 @@ import * as actions from '../actions'; import { coreMock } from '@kbn/core/public/mocks'; import { InvestigateInTimelineAction } from './investigate_in_timeline_action'; import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; const ecsRowData: Ecs = { _id: '1', @@ -28,6 +29,7 @@ const ecsRowData: Ecs = { }, }; +jest.mock('../../../../common/components/user_privileges'); jest.mock('../../../../common/lib/kibana'); jest.mock('../../../../common/lib/apm/use_start_transaction'); jest.mock('../../../../common/hooks/use_app_toasts'); @@ -48,6 +50,12 @@ const mockSendAlertToTimeline = jest.spyOn(actions, 'sendAlertToTimelineAction') (useAppToasts as jest.Mock).mockReturnValue({ addError: jest.fn(), }); +(useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { + crud: true, + read: true, + }, +}); const props = { ecsRowData, @@ -79,4 +87,18 @@ describe('use investigate in timeline hook', () => { }); expect(mockSendAlertToTimeline).toHaveBeenCalledTimes(1); }); + test('it disables the button when the user does not have access to timeline', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { + read: false, + }, + }); + + const wrapper = render( + + + + ); + expect(wrapper.getByTestId('send-alert-to-timeline-button')).toBeDisabled(); + }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_timeline_action.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_timeline_action.tsx index 0b1168e91a7f1..768a80a9df6f1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_timeline_action.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_timeline_action.tsx @@ -8,6 +8,7 @@ import React from 'react'; import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; import { ActionIconItem } from '../../../../common/components/header_actions/action_icon_item'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; import { ACTION_INVESTIGATE_IN_TIMELINE, @@ -32,6 +33,10 @@ const InvestigateInTimelineActionComponent: React.FC ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.test.tsx index 8de172d54a07f..868b390a3ceea 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.test.tsx @@ -19,11 +19,13 @@ import { EuiPopover, EuiContextMenu } from '@elastic/eui'; import * as timelineActions from '../../../../timelines/store/actions'; import { getTimelineTemplate } from '../../../../timelines/containers/api'; import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; jest.mock('../../../../common/lib/kibana'); jest.mock('../../../../timelines/containers/api'); jest.mock('../../../../common/lib/apm/use_start_transaction'); jest.mock('../../../../common/hooks/use_app_toasts'); +jest.mock('../../../../common/components/user_privileges'); const ecsRowData: Ecs = { _id: '1', @@ -269,6 +271,9 @@ describe('useInvestigateInTimeline', () => { }, }, }); + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { read: true }, + }); }); afterEach(() => { jest.clearAllMocks(); @@ -392,4 +397,17 @@ describe('useInvestigateInTimeline', () => { }); }); }); + + describe('privileges', () => { + test('should not return a timeline action when the user does not have sufficient privileges', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { read: false }, + }); + + const { result } = renderHook(() => useInvestigateInTimeline(props), { + wrapper: TestProviders, + }); + expect(result.current.investigateInTimelineActionItems).toHaveLength(0); + }); + }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.tsx index 3b36452f9315d..7a0d02456ad3a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.tsx @@ -32,6 +32,7 @@ import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; import { useStartTransaction } from '../../../../common/lib/apm/use_start_transaction'; import { ALERTS_ACTIONS } from '../../../../common/lib/apm/user_actions'; import { defaultUdtHeaders } from '../../../../timelines/components/timeline/body/column_headers/default_headers'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; interface UseInvestigateInTimelineActionProps { ecsRowData?: Ecs | Ecs[] | null; @@ -189,17 +190,24 @@ export const useInvestigateInTimeline = ({ getExceptionFilter, ]); + const { + timelinePrivileges: { read: canInvestigateInTimeline }, + } = useUserPrivileges(); + const investigateInTimelineActionItems = useMemo( - () => [ - { - key: 'investigate-in-timeline-action-item', - 'data-test-subj': 'investigate-in-timeline-action-item', - disabled: ecsRowData == null, - onClick: investigateInTimelineAlertClick, - name: ACTION_INVESTIGATE_IN_TIMELINE, - }, - ], - [ecsRowData, investigateInTimelineAlertClick] + () => + canInvestigateInTimeline + ? [ + { + key: 'investigate-in-timeline-action-item', + 'data-test-subj': 'investigate-in-timeline-action-item', + disabled: ecsRowData == null, + onClick: investigateInTimelineAlertClick, + name: ACTION_INVESTIGATE_IN_TIMELINE, + }, + ] + : [], + [ecsRowData, investigateInTimelineAlertClick, canInvestigateInTimeline] ); return { diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/translations.ts index b90484e4a795f..0467959a9f7f2 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/translations.ts @@ -140,6 +140,13 @@ export const ALERTS_HEADERS_HOST_CRITICALITY = i18n.translate( } ); +export const ALERTS_HEADERS_SERVICE_RISK_LEVEL = i18n.translate( + 'xpack.securitySolution.eventsViewer.alerts.defaultHeaders.serviceRiskLevel', + { + defaultMessage: 'Service Risk Level', + } +); + export const ALERTS_HEADERS_USER_CRITICALITY = i18n.translate( 'xpack.securitySolution.eventsViewer.alerts.defaultHeaders.userCriticality', { @@ -147,6 +154,13 @@ export const ALERTS_HEADERS_USER_CRITICALITY = i18n.translate( } ); +export const ALERTS_HEADERS_SERVICE_CRITICALITY = i18n.translate( + 'xpack.securitySolution.eventsViewer.alerts.defaultHeaders.serviceCriticality', + { + defaultMessage: 'Service Criticality', + } +); + export const ACTION_INVESTIGATE_IN_TIMELINE = i18n.translate( 'xpack.securitySolution.detectionEngine.alerts.actions.investigateInTimelineTitle', { diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/user_info/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/user_info/index.test.tsx index 8e84d1a5e4f0b..2db975340ca4e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/user_info/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/user_info/index.test.tsx @@ -26,7 +26,7 @@ describe('useUserInfo', () => { services: { application: { capabilities: { - siem: { + siemV2: { crud: true, }, }, @@ -68,7 +68,7 @@ describe('useUserInfo', () => { const wrapper = ({ children }: React.PropsWithChildren) => ( {children} diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/configurations/security_solution_detections/columns.ts b/x-pack/solutions/security/plugins/security_solution/public/detections/configurations/security_solution_detections/columns.ts index 6ca0a67244179..14a5f31b63685 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/configurations/security_solution_detections/columns.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/configurations/security_solution_detections/columns.ts @@ -11,6 +11,8 @@ import { ALERT_USER_CRITICALITY, ALERT_HOST_RISK_SCORE_CALCULATED_LEVEL, ALERT_USER_RISK_SCORE_CALCULATED_LEVEL, + ALERT_SERVICE_RISK_SCORE_CALCULATED_LEVEL, + ALERT_SERVICE_CRITICALITY, } from '../../../../common/field_maps/field_names'; import type { LicenseService } from '../../../../common/license'; import type { ColumnHeaderOptions } from '../../../../common/types'; @@ -46,6 +48,12 @@ export const userRiskLevelColumn: ColumnHeaderOptions = { displayAsText: i18n.ALERTS_HEADERS_USER_RISK_LEVEL, }; +export const serviceRiskLevelColumn: ColumnHeaderOptions = { + columnHeaderType: defaultColumnHeaderType, + id: ALERT_SERVICE_RISK_SCORE_CALCULATED_LEVEL, + displayAsText: i18n.ALERTS_HEADERS_SERVICE_RISK_LEVEL, +}; + const getBaseColumns = ( license?: LicenseService ): Array< @@ -81,6 +89,7 @@ const getBaseColumns = ( }, isPlatinumPlus ? hostRiskLevelColumn : null, isPlatinumPlus ? userRiskLevelColumn : null, + isPlatinumPlus ? serviceRiskLevelColumn : null, isPlatinumPlus ? { columnHeaderType: defaultColumnHeaderType, @@ -95,6 +104,13 @@ const getBaseColumns = ( displayAsText: i18n.ALERTS_HEADERS_USER_CRITICALITY, } : null, + isPlatinumPlus + ? { + columnHeaderType: defaultColumnHeaderType, + id: ALERT_SERVICE_CRITICALITY, + displayAsText: i18n.ALERTS_HEADERS_SERVICE_CRITICALITY, + } + : null, { columnHeaderType: defaultColumnHeaderType, id: 'process.name', diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_alerts_privileges.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_alerts_privileges.test.tsx index e87ebd14b7c88..667585c5f4e56 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_alerts_privileges.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_alerts_privileges.test.tsx @@ -76,6 +76,8 @@ const userPrivilegesInitial: ReturnType = { canAccessFleet: false, }), kibanaSecuritySolutionsPrivileges: { crud: true, read: true }, + timelinePrivileges: { crud: true, read: true }, + notesPrivileges: { crud: true, read: true }, }; describe('useAlertsPrivileges', () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_actions_column.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_actions_column.tsx index 286d377d86f56..d9aa0a730da5a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_actions_column.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_actions_column.tsx @@ -24,6 +24,7 @@ import type { TimelineItem } from '../../../../common/search_strategy'; import { getAlertsDefaultModel } from '../../components/alerts_table/default_config'; import type { State } from '../../../common/store'; import { RowAction } from '../../../common/components/control_columns/row_action'; +import { useUserPrivileges } from '../../../common/components/user_privileges'; // we show a maximum of 6 action buttons // - open flyout @@ -46,11 +47,21 @@ export const getUseActionColumnHook = ACTION_BUTTON_COUNT--; } - // we only want to show the note icon if the new notes system feature flag is enabled + const { + timelinePrivileges: { read: canReadTimelines }, + notesPrivileges: { read: canReadNotes }, + } = useUserPrivileges(); + + // remove space if investigate timeline icon shouldn't be displayed + if (!canReadTimelines) { + ACTION_BUTTON_COUNT--; + } + + // remove space if add notes icon shouldn't be displayed const securitySolutionNotesDisabled = useIsExperimentalFeatureEnabled( 'securitySolutionNotesDisabled' ); - if (securitySolutionNotesDisabled) { + if (!canReadNotes || securitySolutionNotesDisabled) { ACTION_BUTTON_COUNT--; } diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/links.ts b/x-pack/solutions/security/plugins/security_solution/public/detections/links.ts index 1228b21d3363c..20b4e031e5478 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/links.ts @@ -5,7 +5,7 @@ * 2.0. */ import { i18n } from '@kbn/i18n'; -import { ALERTS_PATH, SecurityPageName, SERVER_APP_ID } from '../../common/constants'; +import { ALERTS_PATH, SecurityPageName, SECURITY_FEATURE_ID } from '../../common/constants'; import { ALERTS } from '../app/translations'; import type { LinkItem } from '../common/links/types'; @@ -13,7 +13,7 @@ export const links: LinkItem = { id: SecurityPageName.alerts, title: ALERTS, path: ALERTS_PATH, - capabilities: [`${SERVER_APP_ID}.show`], + capabilities: [`${SECURITY_FEATURE_ID}.show`], globalNavPosition: 3, globalSearchKeywords: [ i18n.translate('xpack.securitySolution.appLinks.alerts', { diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx index 4f8b8a391ea87..b307ea26f8a0b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx @@ -104,7 +104,7 @@ jest.mock('../../../common/lib/kibana', () => { application: { navigateToUrl: jest.fn(), capabilities: { - siem: { crud_alerts: true, read_alerts: true }, + siemV2: { crud_alerts: true, read_alerts: true }, }, }, dataViews: mockDataViewsService, @@ -119,7 +119,7 @@ jest.mock('../../../common/lib/kibana', () => { }, docLinks: { links: { - siem: { + siemV2: { privileges: 'link', }, }, diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.test.tsx index 210884f9754a1..2152d10115b2d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.test.tsx @@ -13,7 +13,6 @@ import { getStepsData, getAboutStepsData, getActionsStepsData, - getHumanizedDuration, getModifiedAboutDetailsData, getPrePackagedTimelineInstallationStatus, determineDetailsValue, @@ -328,50 +327,6 @@ describe('rule helpers', () => { }); }); - describe('getHumanizedDuration', () => { - test('returns from as seconds if from duration is specified in seconds', () => { - const result = getHumanizedDuration('now-62s', '1m'); - - expect(result).toEqual('2s'); - }); - - test('returns from as seconds if from duration is specified in seconds greater than 60', () => { - const result = getHumanizedDuration('now-122s', '1m'); - - expect(result).toEqual('62s'); - }); - - test('returns from as minutes if from duration is specified in minutes', () => { - const result = getHumanizedDuration('now-660s', '5m'); - - expect(result).toEqual('6m'); - }); - - test('returns from as minutes if from duration is specified in minutes greater than 60', () => { - const result = getHumanizedDuration('now-6600s', '5m'); - - expect(result).toEqual('105m'); - }); - - test('returns from as hours if from duration is specified in hours', () => { - const result = getHumanizedDuration('now-7500s', '5m'); - - expect(result).toEqual('2h'); - }); - - test('returns from as if from is not parsable as dateMath', () => { - const result = getHumanizedDuration('randomstring', '5m'); - - expect(result).toEqual('NaNs'); - }); - - test('returns from as 5m if interval is not parsable as dateMath', () => { - const result = getHumanizedDuration('now-300s', 'randomstring'); - - expect(result).toEqual('5m'); - }); - }); - describe('getScheduleStepsData', () => { test('returns expected ScheduleStep rule object', () => { const mockedRule = { diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx index 4136b21e96106..1dff767667450 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx @@ -5,8 +5,6 @@ * 2.0. */ -import dateMath from '@kbn/datemath'; -import moment from 'moment'; import memoizeOne from 'memoize-one'; import { useLocation } from 'react-router-dom'; @@ -22,6 +20,7 @@ import { ENDPOINT_LIST_ID } from '@kbn/securitysolution-list-constants'; import type { Filter } from '@kbn/es-query'; import type { ActionVariables } from '@kbn/triggers-actions-ui-plugin/public'; import { requiredOptional } from '@kbn/zod-helpers'; +import { toSimpleRuleSchedule } from '../../../../../common/api/detection_engine/model/rule_schema/to_simple_rule_schedule'; import { ALERT_SUPPRESSION_FIELDS_FIELD_NAME, ALERT_SUPPRESSION_DURATION_TYPE_FIELD_NAME, @@ -191,43 +190,21 @@ export const getDefineStepsData = (rule: RuleResponse): DefineStepRule => ({ }); export const getScheduleStepsData = (rule: RuleResponse): ScheduleStepRule => { - const { interval, from } = rule; - const fromHumanizedValue = getHumanizedDuration(from, interval); + const simpleRuleSchedule = toSimpleRuleSchedule(rule); - return { - interval, - from: fromHumanizedValue, - }; -}; - -/** - * Converts seconds to duration string, like "1h", "30m" or "15s" - */ -export const secondsToDurationString = (seconds: number): string => { - if (seconds === 0) { - return `0s`; - } - - if (seconds % 3600 === 0) { - return `${seconds / 3600}h`; - } else if (seconds % 60 === 0) { - return `${seconds / 60}m`; - } else { - return `${seconds}s`; + if (simpleRuleSchedule) { + return { + interval: simpleRuleSchedule.interval, + from: simpleRuleSchedule.lookback, + }; } -}; - -export const getHumanizedDuration = (from: string, interval: string): string => { - const fromValue = dateMath.parse(from) ?? moment(); - const intervalValue = dateMath.parse(`now-${interval}`) ?? moment(); - - const fromDuration = moment.duration(intervalValue.diff(fromValue)); - // Basing calculations off floored seconds count as moment durations weren't precise - const intervalDuration = Math.floor(fromDuration.asSeconds()); - // For consistency of display value - - return secondsToDurationString(intervalDuration); + return { + interval: rule.interval, + // Fallback to zero look-back since UI isn't able to handle negative + // look-back + from: '0s', + }; }; export const getAboutStepsData = (rule: RuleResponse, detailsView: boolean): AboutStepRule => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/asset_criticality_selector.stories.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/asset_criticality_selector.stories.tsx index 042d6be1d2eb6..860a75609cf9c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/asset_criticality_selector.stories.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/asset_criticality_selector.stories.tsx @@ -12,6 +12,7 @@ import { ThemeProvider } from 'styled-components'; import { euiLightVars } from '@kbn/ui-theme'; import { TestProvider } from '@kbn/expandable-flyout/src/test/provider'; +import { EntityType } from '../../../../common/entity_analytics/types'; import { StorybookProviders } from '../../../common/mock/storybook_providers'; import { AssetCriticalitySelector } from './asset_criticality_selector'; import type { State } from './use_asset_criticality'; @@ -43,7 +44,7 @@ export const Default: Story = () => {
@@ -58,7 +59,7 @@ export const Compressed: Story = () => {
@@ -74,7 +75,7 @@ export const Loading: Story = () => {
diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/asset_criticality_selector.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/asset_criticality_selector.test.tsx index 691c240e651a5..60738deabfed1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/asset_criticality_selector.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/asset_criticality_selector.test.tsx @@ -10,6 +10,7 @@ import { render } from '@testing-library/react'; import React from 'react'; import { AssetCriticalitySelector } from './asset_criticality_selector'; import type { State } from './use_asset_criticality'; +import { EntityType } from '../../../../common/entity_analytics/types'; const criticality = { status: 'create', @@ -27,7 +28,7 @@ describe('AssetCriticalitySelector', () => { const { getByTestId } = render( , { wrapper: TestProviders, @@ -41,7 +42,7 @@ describe('AssetCriticalitySelector', () => { const { getByTestId } = render( , { diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/asset_criticality_selector.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/asset_criticality_selector.tsx index 51ebecedac3d4..60ecd975697c7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/asset_criticality_selector.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/asset_criticality_selector.tsx @@ -35,6 +35,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { css } from '@emotion/css'; import { i18n } from '@kbn/i18n'; import useToggle from 'react-use/lib/useToggle'; +import { EntityTypeToIdentifierField } from '../../../../common/entity_analytics/types'; import { PICK_ASSET_CRITICALITY } from './translations'; import { AssetCriticalityBadge } from './asset_criticality_badge'; import type { Entity, State } from './use_asset_criticality'; @@ -59,7 +60,7 @@ const AssetCriticalitySelectorComponent: React.FC<{ const onSave = (value: CriticalityLevelWithUnassigned) => { criticality.mutation.mutate({ criticalityLevel: value, - idField: `${entity.type}.name`, + idField: EntityTypeToIdentifierField[entity.type], idValue: entity.name, }); toggleModal(false); diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/use_asset_criticality.test.ts b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/use_asset_criticality.test.ts index df9e39022f1e3..786d465149413 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/use_asset_criticality.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/use_asset_criticality.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { EntityType } from '../../../../common/entity_analytics/types'; import { renderMutation, renderQuery, @@ -71,7 +72,7 @@ describe('useAssetCriticality', () => { mockFetchAssetCriticalityPrivileges.mockResolvedValue({ has_all_required: true }); mockDeleteAssetCriticality.mockResolvedValue({}); mockCreateAssetCriticality.mockResolvedValue({}); - const entity: Entity = { name: 'test_entity_name', type: 'host' }; + const entity: Entity = { name: 'test_entity_name', type: EntityType.host }; const { mutation } = await renderWrappedHook(() => useAssetCriticalityData({ entity })); @@ -90,7 +91,7 @@ describe('useAssetCriticality', () => { mockFetchAssetCriticalityPrivileges.mockResolvedValue({ has_all_required: true }); mockDeleteAssetCriticality.mockResolvedValue({}); mockCreateAssetCriticality.mockResolvedValue({}); - const entity: Entity = { name: 'test_entity_name', type: 'host' }; + const entity: Entity = { name: 'test_entity_name', type: EntityType.host }; const { mutation } = await renderWrappedHook(() => useAssetCriticalityData({ entity })); diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/use_asset_criticality.ts b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/use_asset_criticality.ts index d5ecde239f35a..6e11bfb267d71 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/use_asset_criticality.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/use_asset_criticality.ts @@ -8,6 +8,8 @@ import type { UseMutationResult, UseQueryResult } from '@tanstack/react-query'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import type { SecurityAppError } from '@kbn/securitysolution-t-grid'; +import type { EntityType } from '../../../../common/entity_analytics/types'; +import { EntityTypeToIdentifierField } from '../../../../common/entity_analytics/types'; import type { EntityAnalyticsPrivileges } from '../../../../common/api/entity_analytics'; import type { CriticalityLevelWithUnassigned } from '../../../../common/entity_analytics/asset_criticality/types'; import { useHasSecurityCapability } from '../../../helper_hooks'; @@ -58,7 +60,11 @@ export const useAssetCriticalityData = ({ const privileges = useAssetCriticalityPrivileges(entity.name); const query = useQuery({ queryKey: QUERY_KEY, - queryFn: () => fetchAssetCriticality({ idField: `${entity.type}.name`, idValue: entity.name }), + queryFn: () => + fetchAssetCriticality({ + idField: EntityTypeToIdentifierField[entity.type], + idValue: entity.name, + }), retry: (failureCount, error) => error.body.statusCode === 404 && failureCount > 0, enabled, }); @@ -128,5 +134,5 @@ export interface ModalState { export interface Entity { name: string; - type: 'host' | 'user'; + type: EntityType; } diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/hooks/use_risk_input_actions_panels.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/hooks/use_risk_input_actions_panels.test.tsx index 17e5dc616e536..4c2bd22fd525d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/hooks/use_risk_input_actions_panels.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/hooks/use_risk_input_actions_panels.test.tsx @@ -13,6 +13,7 @@ import React from 'react'; import { TestProviders } from '../../../../common/mock'; import { alertInputDataMock } from '../mocks'; import { useRiskInputActionsPanels } from './use_risk_input_actions_panels'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; const casesServiceMock = casesPluginMock.createStartContract(); const mockCanUseCases = jest.fn().mockReturnValue({ @@ -42,6 +43,13 @@ jest.mock('@kbn/kibana-react-plugin/public', () => { }; }); +jest.mock('../../../../common/components/user_privileges'); +(useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { + read: false, + }, +}); + const TestMenu = ({ panels }: { panels: EuiContextMenuPanelDescriptor[] }) => ( ); @@ -89,4 +97,22 @@ describe('useRiskInputActionsPanels', () => { expect(container).not.toHaveTextContent('Add to existing case'); expect(container).not.toHaveTextContent('Add to new case'); }); + + it('displays the timeline action when user has sufficient privileges', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { read: true }, + }); + const { container } = customRender(); + + expect(container).toHaveTextContent('Add to new timeline'); + }); + + it('does NOT display the timeline action when user has NO insufficient privileges', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { read: false }, + }); + const { container } = customRender(); + + expect(container).not.toHaveTextContent('Add to new timeline'); + }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/hooks/use_risk_input_actions_panels.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/hooks/use_risk_input_actions_panels.tsx index 03b25bc85d8db..232b1f9f9d43d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/hooks/use_risk_input_actions_panels.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/hooks/use_risk_input_actions_panels.tsx @@ -16,6 +16,7 @@ import { get } from 'lodash/fp'; import { ALERT_RULE_NAME } from '@kbn/rule-data-utils'; import { useRiskInputActions } from './use_risk_input_actions'; import type { InputAlert } from '../../../hooks/use_risk_contributing_alerts'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; export const useRiskInputActionsPanels = (inputs: InputAlert[], closePopover: () => void) => { const { cases: casesService } = useKibana<{ cases?: CasesService }>().services; @@ -25,6 +26,9 @@ export const useRiskInputActionsPanels = (inputs: InputAlert[], closePopover: () ); const userCasesPermissions = casesService?.helpers.canUseCases([SECURITY_SOLUTION_OWNER]); const hasCasesPermissions = userCasesPermissions?.create && userCasesPermissions?.read; + const { + timelinePrivileges: { read: canAddToTimeline }, + } = useUserPrivileges(); return useMemo(() => { const timelinePanel = { @@ -68,33 +72,42 @@ export const useRiskInputActionsPanels = (inputs: InputAlert[], closePopover: () /> ), id: 0, - items: hasCasesPermissions - ? [ - timelinePanel, - { - name: ( - - ), + items: [ + ...(canAddToTimeline ? [timelinePanel] : []), + ...(hasCasesPermissions + ? [ + { + name: ( + + ), - onClick: addToNewCaseClick, - }, + onClick: addToNewCaseClick, + }, - { - name: ( - - ), + { + name: ( + + ), - onClick: addToExistingCase, - }, - ] - : [timelinePanel], + onClick: addToExistingCase, + }, + ] + : []), + ], }, ]; - }, [addToExistingCase, addToNewCaseClick, addToNewTimeline, inputs, hasCasesPermissions]); + }, [ + addToExistingCase, + addToNewCaseClick, + addToNewTimeline, + inputs, + hasCasesPermissions, + canAddToTimeline, + ]); }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/index.tsx index 6881814f391de..5ffef692bbe67 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/index.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; +import type { CloudPostureEntityIdentifier } from '../../../cloud_security_posture/components/entity_insight'; import type { EntityType } from '../../../../common/search_strategy'; import { EntityDetailsLeftPanelTab } from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header'; import { PREFIX } from '../../../flyout/shared/test_ids'; @@ -38,7 +39,7 @@ export const getInsightsInputTab = ({ fieldName, }: { name: string; - fieldName: 'host.name' | 'user.name'; + fieldName: CloudPostureEntityIdentifier; }) => { return { id: EntityDetailsLeftPanelTab.CSP_INSIGHTS, diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/tabs/risk_inputs/risk_inputs_tab.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/tabs/risk_inputs/risk_inputs_tab.tsx index b8547a838060d..517cd14b98e6e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/tabs/risk_inputs/risk_inputs_tab.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/tabs/risk_inputs/risk_inputs_tab.tsx @@ -25,12 +25,8 @@ import { useRiskContributingAlerts } from '../../../../hooks/use_risk_contributi import { PreferenceFormattedDate } from '../../../../../common/components/formatted_date'; import { useRiskScore } from '../../../../api/hooks/use_risk_score'; -import type { EntityRiskScore } from '../../../../../../common/search_strategy'; -import { - buildHostNamesFilter, - buildUserNamesFilter, - EntityType, -} from '../../../../../../common/search_strategy'; +import type { EntityRiskScore, EntityType } from '../../../../../../common/search_strategy'; +import { buildEntityNameFilter } from '../../../../../../common/search_strategy'; import { AssetCriticalityBadge } from '../../../asset_criticality'; import { RiskInputsUtilityBar } from '../../components/utility_bar'; import { ActionColumn } from '../../components/action_column'; @@ -58,12 +54,7 @@ export const RiskInputsTab = ({ const [selectedItems, setSelectedItems] = useState([]); const nameFilterQuery = useMemo(() => { - // TODO Add support for services on a follow-up PR - if (entityType === EntityType.host) { - return buildHostNamesFilter([entityName]); - } else if (entityType === EntityType.user) { - return buildUserNamesFilter([entityName]); - } + return buildEntityNameFilter(entityType, [entityName]); }, [entityName, entityType]); const { diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/helpers.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/helpers.tsx index d0b7584998afe..3ae178b22ac5a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/helpers.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/helpers.tsx @@ -34,7 +34,7 @@ export const getEntityType = (record: Entity): EntityType => { export const EntityIconByType: Record = { [EntityType.user]: 'user', [EntityType.host]: 'storage', - [EntityType.service]: 'gear', + [EntityType.service]: 'node', [EntityType.universal]: 'globe', // random value since we don't support universal entity type }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_score_enable_section.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_score_enable_section.tsx index 6bc078df84d6f..98076b6a26d7f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_score_enable_section.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_score_enable_section.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { EuiFlexGroup, EuiFlexItem, @@ -94,12 +95,13 @@ const RiskEngineStatusRow: React.FC<{ diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/translations.ts index f291c5e399819..a11ba6f8c5d8c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/translations.ts @@ -202,6 +202,13 @@ export const RISK_ENGINE_NEXT_RUN_TIME = (timeInMinutes: string) => values: { timeInMinutes }, }); +export const RISK_ENGINE_STATUS_SWITCH_LABEL = i18n.translate( + 'xpack.securitySolution.riskScore.riskEngineStatus', + { + defaultMessage: 'Risk engine status', + } +); + export const RUN_RISK_SCORE_ENGINE = i18n.translate('xpack.securitySolution.riskScore.runEngine', { defaultMessage: 'Run Engine', }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/details/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/details/index.tsx index f6bb109b24cbb..ad01ad22077af 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/details/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/details/index.tsx @@ -183,7 +183,10 @@ const HostDetailsComponent: React.FC = ({ detailName, hostDeta [rawFilteredQuery] ); - const entity = useMemo(() => ({ type: 'host' as const, name: detailName }), [detailName]); + const entity = useMemo( + () => ({ type: EntityType.host as const, name: detailName }), + [detailName] + ); const privileges = useAssetCriticalityPrivileges(entity.name); const refetchRiskScore = useRefetchOverviewPageRiskScore(HOST_OVERVIEW_RISK_SCORE_QUERY_ID); diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/links.ts b/x-pack/solutions/security/plugins/security_solution/public/explore/links.ts index a65eccc95c372..18f176494fffe 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/links.ts @@ -11,7 +11,7 @@ import { NETWORK_PATH, USERS_PATH, EXPLORE_PATH, - SERVER_APP_ID, + SECURITY_FEATURE_ID, SecurityPageName, } from '../../common/constants'; import { EXPLORE, HOSTS, NETWORK, USERS } from '../app/translations'; @@ -34,7 +34,7 @@ const networkLinks: LinkItem = { defaultMessage: 'Network', }), ], - capabilities: [`${SERVER_APP_ID}.show`], + capabilities: [`${SECURITY_FEATURE_ID}.show`], links: [ { id: SecurityPageName.networkFlows, @@ -97,7 +97,7 @@ const usersLinks: LinkItem = { defaultMessage: 'Users', }), ], - capabilities: [`${SERVER_APP_ID}.show`], + capabilities: [`${SECURITY_FEATURE_ID}.show`], links: [ { id: SecurityPageName.usersAll, @@ -152,7 +152,7 @@ const hostsLinks: LinkItem = { defaultMessage: 'Hosts', }), ], - capabilities: [`${SERVER_APP_ID}.show`], + capabilities: [`${SECURITY_FEATURE_ID}.show`], links: [ { id: SecurityPageName.hostsAll, @@ -209,7 +209,7 @@ export const exploreLinks: LinkItem = { title: EXPLORE, path: EXPLORE_PATH, globalNavPosition: 9, - capabilities: [`${SERVER_APP_ID}.show`], + capabilities: [`${SECURITY_FEATURE_ID}.show`], globalSearchKeywords: [ i18n.translate('xpack.securitySolution.appLinks.explore', { defaultMessage: 'Explore', diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/network.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/network.test.tsx index 4f44045cbf6f3..ab4627f911165 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/network.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/network.test.tsx @@ -82,7 +82,7 @@ jest.mock('../../../common/lib/kibana', () => { application: { ...original.useKibana().services.application, capabilities: { - siem: { crud_alerts: true, read_alerts: true }, + siemV2: { crud_alerts: true, read_alerts: true }, maps: mockMapVisibility(), }, navigateToApp: mockNavigateToApp, diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/index.tsx index b9790d4ad2b46..8d86a92894231 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/index.tsx @@ -183,7 +183,7 @@ const UsersDetailsComponent: React.FC = ({ [detailName] ); - const entity = useMemo(() => ({ type: 'user' as const, name: detailName }), [detailName]); + const entity = useMemo(() => ({ type: EntityType.user, name: detailName }), [detailName]); const privileges = useAssetCriticalityPrivileges(entity.name); const refetchRiskScore = useRefetchOverviewPageRiskScore(USER_OVERVIEW_RISK_SCORE_QUERY_ID); diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/attach_to_active_timeline.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/attach_to_active_timeline.test.tsx index ad9f2444882e7..4566676fe04b8 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/attach_to_active_timeline.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/attach_to_active_timeline.test.tsx @@ -24,7 +24,7 @@ const mockSetAttachToTimeline = jest.fn(); describe('AttachToActiveTimeline', () => { it('should render the component for an unsaved timeline', () => { (useUserPrivileges as jest.Mock).mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true }, + timelinePrivileges: { crud: true }, }); const mockStore = createMockStore({ ...mockGlobalState, diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/notes_details.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/notes_details.test.tsx index c6f8b51817de7..feb644efa8ce4 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/notes_details.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/notes_details.test.tsx @@ -84,7 +84,8 @@ describe('NotesDetails', () => { beforeEach(() => { jest.clearAllMocks(); useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true }, + notesPrivileges: { crud: true }, + timelinePrivileges: { crud: true }, }); (useWhichFlyout as jest.Mock).mockReturnValue(Flyouts.timeline); (useBasicDataFromDetailsData as jest.Mock).mockReturnValue({ isAlert: true }); @@ -196,7 +197,8 @@ describe('NotesDetails', () => { it('should not render the add note section for users without crud privileges', () => { useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: false }, + notesPrivileges: { crud: false }, + timelinePrivileges: { crud: false }, }); const { queryByTestId } = renderNotesDetails(); diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/notes_details.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/notes_details.tsx index 8877e1759c475..e9c667d748be7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/notes_details.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/notes_details.tsx @@ -56,12 +56,12 @@ export const NotesDetails = memo(() => { const { addError: addErrorToast } = useAppToasts(); const dispatch = useDispatch(); const { eventId, dataFormattedForFieldBrowser } = useDocumentDetailsContext(); - const { kibanaSecuritySolutionsPrivileges } = useUserPrivileges(); + const { notesPrivileges } = useUserPrivileges(); const { basicAlertData: basicData } = useInvestigationGuide({ dataFormattedForFieldBrowser, }); - const canCreateNotes = kibanaSecuritySolutionsPrivileges.crud; + const canCreateNotes = notesPrivileges.crud; // will drive the value we send to the AddNote component // if true (timeline is saved and the user kept the checkbox checked) we'll send the timelineId to the AddNote component diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/prevalence_details.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/prevalence_details.test.tsx index e0bef746b213b..e768719a00be4 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/prevalence_details.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/prevalence_details.test.tsx @@ -20,6 +20,7 @@ import { PREVALENCE_DETAILS_TABLE_VALUE_CELL_TEST_ID, PREVALENCE_DETAILS_TABLE_PREVIEW_LINK_CELL_TEST_ID, PREVALENCE_DETAILS_TABLE_UPSELL_CELL_TEST_ID, + PREVALENCE_DETAILS_TABLE_INVESTIGATE_IN_TIMELINE_BUTTON_TEST_ID, } from './test_ids'; import { usePrevalence } from '../../shared/hooks/use_prevalence'; import { TestProviders } from '../../../../common/mock'; @@ -31,8 +32,10 @@ import { HOST_PREVIEW_BANNER } from '../../right/components/host_entity_overview import { UserPreviewPanelKey } from '../../../entity_details/user_right'; import { USER_PREVIEW_BANNER } from '../../right/components/user_entity_overview'; import { createTelemetryServiceMock } from '../../../../common/lib/telemetry/telemetry_service.mock'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; jest.mock('@kbn/expandable-flyout'); +jest.mock('../../../../common/components/user_privileges'); const mockedTelemetry = createTelemetryServiceMock(); jest.mock('../../../../common/lib/kibana', () => { @@ -134,6 +137,7 @@ describe('PrevalenceDetails', () => { jest.clearAllMocks(); licenseServiceMock.isPlatinumPlus.mockReturnValue(true); jest.mocked(useExpandableFlyoutApi).mockReturnValue(mockFlyoutApi); + (useUserPrivileges as jest.Mock).mockReturnValue({ timelinePrivileges: { read: true } }); }); it('should render the table with all data if license is platinum', () => { @@ -219,7 +223,7 @@ describe('PrevalenceDetails', () => { ).not.toHaveTextContent('10%'); }); - it('should render formatted numbers for the alert and document count columns', () => { + it('should render formatted numbers for the alert and document count columns and be clickable buttons', () => { (usePrevalence as jest.Mock).mockReturnValue({ loading: false, error: false, @@ -235,7 +239,7 @@ describe('PrevalenceDetails', () => { ], }); - const { getByTestId } = render( + const { getByTestId, getAllByTestId } = render( @@ -254,6 +258,52 @@ describe('PrevalenceDetails', () => { expect(getByTestId(PREVALENCE_DETAILS_TABLE_USER_PREVALENCE_CELL_TEST_ID)).toHaveTextContent( '10%' ); + + expect( + getAllByTestId(PREVALENCE_DETAILS_TABLE_INVESTIGATE_IN_TIMELINE_BUTTON_TEST_ID).length + ).toBeGreaterThan(1); + }); + + it('should render formatted numbers as text if user lacks timeline read privileges', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ timelinePrivileges: { read: false } }); + (usePrevalence as jest.Mock).mockReturnValue({ + loading: false, + error: false, + data: [ + { + field: 'field1', + values: ['value1'], + alertCount: 1000, + docCount: 2000000, + hostPrevalence: 0.05, + userPrevalence: 0.1, + }, + ], + }); + + const { getByTestId, queryAllByTestId } = render( + + + + + + ); + + expect(getByTestId(PREVALENCE_DETAILS_TABLE_TEST_ID)).toBeInTheDocument(); + expect(getByTestId(PREVALENCE_DETAILS_TABLE_FIELD_CELL_TEST_ID)).toHaveTextContent('field1'); + expect(getByTestId(PREVALENCE_DETAILS_TABLE_VALUE_CELL_TEST_ID)).toHaveTextContent('value1'); + expect(getByTestId(PREVALENCE_DETAILS_TABLE_ALERT_COUNT_CELL_TEST_ID)).toHaveTextContent('1k'); + expect(getByTestId(PREVALENCE_DETAILS_TABLE_DOC_COUNT_CELL_TEST_ID)).toHaveTextContent('2M'); + expect(getByTestId(PREVALENCE_DETAILS_TABLE_HOST_PREVALENCE_CELL_TEST_ID)).toHaveTextContent( + '5%' + ); + expect(getByTestId(PREVALENCE_DETAILS_TABLE_USER_PREVALENCE_CELL_TEST_ID)).toHaveTextContent( + '10%' + ); + + expect( + queryAllByTestId(PREVALENCE_DETAILS_TABLE_INVESTIGATE_IN_TIMELINE_BUTTON_TEST_ID).length + ).not.toBeGreaterThan(1); }); it('should render multiple values in value column', () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/prevalence_details.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/prevalence_details.tsx index 77ab6eb66df31..d2c90f43e1a5d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/prevalence_details.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/prevalence_details.tsx @@ -39,6 +39,8 @@ import { PREVALENCE_DETAILS_TABLE_TEST_ID, PREVALENCE_DETAILS_UPSELL_TEST_ID, PREVALENCE_DETAILS_TABLE_UPSELL_CELL_TEST_ID, + PREVALENCE_DETAILS_TABLE_INVESTIGATE_IN_TIMELINE_BUTTON_TEST_ID, + PREVALENCE_DETAILS_TABLE_COUNT_TEXT_BUTTON_TEST_ID, } from './test_ids'; import { useDocumentDetailsContext } from '../../shared/context'; import { @@ -49,6 +51,7 @@ import { getEmptyTagValue } from '../../../../common/components/empty_value'; import { IS_OPERATOR } from '../../../../../common/types'; import { hasPreview, PreviewLink } from '../../../shared/components/preview_link'; import { CellActions } from '../../shared/components/cell_actions'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; export const PREVALENCE_TAB_ID = 'prevalence'; const DEFAULT_FROM = 'now-30d'; @@ -84,6 +87,10 @@ interface PrevalenceDetailsRow extends PrevalenceData { * Scope id to pass to the preview link */ scopeId: string; + /** + * True if user have the correct timeline read privilege + */ + canUseTimeline: boolean; } const columns: Array> = [ @@ -169,17 +176,29 @@ const columns: Array> = [ const dataProviders = data.values.map((value) => getDataProvider(data.field, `timeline-indicator-${data.field}-${value}`, value) ); - return data.alertCount > 0 ? ( + + if (data.alertCount === 0) { + return getEmptyTagValue(); + } + + const alertCount = ; + if (!data.canUseTimeline) { + return ( + + {alertCount} + + ); + } + return ( - + {alertCount} - ) : ( - getEmptyTagValue() ); }, width: '10%', @@ -224,18 +243,30 @@ const columns: Array> = [ ), ], })); - return data.docCount > 0 ? ( + + if (data.docCount === 0) { + return getEmptyTagValue(); + } + + const docCount = ; + if (!data.canUseTimeline) { + return ( + + {docCount} + + ); + } + return ( - + {docCount} - ) : ( - getEmptyTagValue() ); }, width: '10%', @@ -325,6 +356,10 @@ export const PrevalenceDetails: React.FC = () => { const { dataFormattedForFieldBrowser, investigationFields, scopeId } = useDocumentDetailsContext(); + const { + timelinePrivileges: { read: canUseTimeline }, + } = useUserPrivileges(); + const isPlatinumPlus = useLicense().isPlatinumPlus(); // these two are used by the usePrevalence hook to fetch the data @@ -377,8 +412,9 @@ export const PrevalenceDetails: React.FC = () => { to: absoluteEnd, isPlatinumPlus, scopeId, + canUseTimeline, })), - [data, absoluteStart, absoluteEnd, isPlatinumPlus, scopeId] + [data, absoluteStart, absoluteEnd, canUseTimeline, isPlatinumPlus, scopeId] ); const upsell = ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/test_ids.ts b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/test_ids.ts index 6979fa9cfa053..6765ed751b359 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/test_ids.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/components/test_ids.ts @@ -32,6 +32,10 @@ export const PREVALENCE_DETAILS_TABLE_ALERT_COUNT_CELL_TEST_ID = `${PREVALENCE_DETAILS_TABLE_TEST_ID}AlertCountCell` as const; export const PREVALENCE_DETAILS_TABLE_DOC_COUNT_CELL_TEST_ID = `${PREVALENCE_DETAILS_TABLE_TEST_ID}DocCountCell` as const; +export const PREVALENCE_DETAILS_TABLE_INVESTIGATE_IN_TIMELINE_BUTTON_TEST_ID = + `${PREVALENCE_DETAILS_TABLE_TEST_ID}InvestigateInTimelineButton` as const; +export const PREVALENCE_DETAILS_TABLE_COUNT_TEXT_BUTTON_TEST_ID = + `${PREVALENCE_DETAILS_TABLE_TEST_ID}CountTextButton` as const; export const PREVALENCE_DETAILS_TABLE_HOST_PREVALENCE_CELL_TEST_ID = `${PREVALENCE_DETAILS_TABLE_TEST_ID}HostPrevalenceCell` as const; export const PREVALENCE_DETAILS_TABLE_USER_PREVALENCE_CELL_TEST_ID = diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/index.tsx index 6dcf9da06d2b6..63aaeca39685b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/left/index.tsx @@ -11,6 +11,7 @@ import React, { memo, useMemo } from 'react'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; import { useUiSetting$ } from '@kbn/kibana-react-plugin/public'; import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; +import { useUserPrivileges } from '../../../common/components/user_privileges'; import { ENABLE_VISUALIZATIONS_IN_FLYOUT_SETTING } from '../../../../common/constants'; import { DocumentDetailsLeftPanelKey } from '../shared/constants/panel_keys'; import { useKibana } from '../../../common/lib/kibana'; @@ -39,6 +40,9 @@ export const LeftPanel: FC> = memo(({ path }) => { const securitySolutionNotesDisabled = useIsExperimentalFeatureEnabled( 'securitySolutionNotesDisabled' ); + const { + notesPrivileges: { read: canSeeNotes }, + } = useUserPrivileges(); const [visualizationInFlyoutEnabled] = useUiSetting$( ENABLE_VISUALIZATIONS_IN_FLYOUT_SETTING @@ -49,14 +53,20 @@ export const LeftPanel: FC> = memo(({ path }) => { eventKind === EventKind.signal ? [tabs.insightsTab, tabs.investigationTab, tabs.responseTab] : [tabs.insightsTab]; - if (!securitySolutionNotesDisabled && !isPreview) { + if (canSeeNotes && !securitySolutionNotesDisabled && !isPreview) { tabList.push(tabs.notesTab); } if (visualizationInFlyoutEnabled && !isPreview) { return [tabs.visualizeTab, ...tabList]; } return tabList; - }, [eventKind, isPreview, securitySolutionNotesDisabled, visualizationInFlyoutEnabled]); + }, [ + eventKind, + isPreview, + canSeeNotes, + securitySolutionNotesDisabled, + visualizationInFlyoutEnabled, + ]); const selectedTabId = useMemo(() => { const defaultTab = tabsDisplayed[0].id; diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/right/components/assignees.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/right/components/assignees.test.tsx index 3c27165f8cc11..32e27b36e25ac 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/right/components/assignees.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/right/components/assignees.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { render } from '@testing-library/react'; +import { render, fireEvent } from '@testing-library/react'; import { ASSIGNEES_ADD_BUTTON_TEST_ID, @@ -132,12 +132,12 @@ describe('', () => { const { getByTestId, getByText } = renderAssignees('test-event', assignees); // Update assignees - getByTestId(ASSIGNEES_ADD_BUTTON_TEST_ID).click(); - getByText('User 1').click(); - getByText('User 3').click(); + fireEvent.click(getByTestId(ASSIGNEES_ADD_BUTTON_TEST_ID)); + fireEvent.click(getByText('User 1')); + fireEvent.click(getByText('User 3')); // Apply assignees - getByTestId(ASSIGNEES_APPLY_BUTTON_TEST_ID).click(); + fireEvent.click(getByTestId(ASSIGNEES_APPLY_BUTTON_TEST_ID)); expect(setAlertAssigneesMock).toHaveBeenCalledWith( { diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/right/components/notes.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/right/components/notes.test.tsx index 3e07d9df1f79d..5ad5d878f6946 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/right/components/notes.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/right/components/notes.test.tsx @@ -50,7 +50,7 @@ describe('', () => { beforeEach(() => { jest.clearAllMocks(); (useUserPrivileges as jest.Mock).mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true }, + notesPrivileges: { crud: true, read: true }, }); (useNavigateToLeftPanel as jest.Mock).mockReturnValue({ navigateToLeftPanel: mockNavigateToLeftPanel, @@ -280,7 +280,7 @@ describe('', () => { it('should show View note button if user does not have the correct privileges but notes have already been created', () => { (useUserPrivileges as jest.Mock).mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: false }, + notesPrivileges: { crud: false, read: true }, }); const contextValue = { @@ -313,7 +313,7 @@ describe('', () => { it('should show a - if user does not have the correct privileges and no notes have been created', () => { (useUserPrivileges as jest.Mock).mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: false }, + notesPrivileges: { read: true, crud: false }, }); const { getByText, queryByTestId } = render( diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/right/components/notes.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/right/components/notes.tsx index 46377ee6db628..6538854b93fe6 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/right/components/notes.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/right/components/notes.tsx @@ -71,7 +71,7 @@ export const Notes = memo(() => { const dispatch = useDispatch(); const { eventId, isPreview } = useDocumentDetailsContext(); const { addError: addErrorToast } = useAppToasts(); - const { kibanaSecuritySolutionsPrivileges } = useUserPrivileges(); + const { notesPrivileges } = useUserPrivileges(); const { navigateToLeftPanel: openExpandedFlyoutNotesTab, isEnabled: isLinkEnabled } = useNavigateToLeftPanel({ @@ -79,13 +79,15 @@ export const Notes = memo(() => { }); const isNotesDisabled = !isLinkEnabled || isPreview; + const cannotAddNotes = isNotesDisabled || !notesPrivileges.crud; + const cannotReadNotes = isNotesDisabled || !notesPrivileges.read; useEffect(() => { - // only fetch notes if we are not in a preview panel, or not in a rule preview workflow - if (!isNotesDisabled) { + // fetch notes only if we are not in a preview panel, or not in a rule preview workflow, and if the user has the correct privileges + if (!cannotReadNotes) { dispatch(fetchNotesByDocumentIds({ documentIds: [eventId] })); } - }, [dispatch, eventId, isNotesDisabled]); + }, [dispatch, eventId, cannotReadNotes]); const fetchStatus = useSelector((state: State) => selectFetchNotesByDocumentIdsStatus(state)); const fetchError = useSelector((state: State) => selectFetchNotesByDocumentIdsError(state)); @@ -106,7 +108,7 @@ export const Notes = memo(() => { @@ -117,7 +119,7 @@ export const Notes = memo(() => { /> ), - [isNotesDisabled, notes.length, openExpandedFlyoutNotesTab] + [cannotReadNotes, notes.length, openExpandedFlyoutNotesTab] ); const addNoteButton = useMemo( () => ( @@ -125,21 +127,21 @@ export const Notes = memo(() => { iconType="plusInCircle" onClick={openExpandedFlyoutNotesTab} size="s" - disabled={isNotesDisabled} + disabled={cannotAddNotes} aria-label={ADD_NOTE_BUTTON} data-test-subj={NOTES_ADD_NOTE_BUTTON_TEST_ID} > {ADD_NOTE_BUTTON} ), - [isNotesDisabled, openExpandedFlyoutNotesTab] + [cannotAddNotes, openExpandedFlyoutNotesTab] ); const addNoteButtonIcon = useMemo( () => ( { data-test-subj={NOTES_ADD_NOTE_ICON_BUTTON_TEST_ID} /> ), - [ - euiTheme.size.xs, - isNotesDisabled, - kibanaSecuritySolutionsPrivileges.crud, - openExpandedFlyoutNotesTab, - ] + [euiTheme.size.xs, cannotAddNotes, openExpandedFlyoutNotesTab] ); return ( @@ -174,14 +171,14 @@ export const Notes = memo(() => { ) : ( <> {notes.length === 0 ? ( - <>{kibanaSecuritySolutionsPrivileges.crud ? addNoteButton : getEmptyTagValue()} + <>{notesPrivileges.crud ? addNoteButton : getEmptyTagValue()} ) : ( - {kibanaSecuritySolutionsPrivileges.crud ? addNoteButtonIcon : viewNotesButton} + {notesPrivileges.crud ? addNoteButtonIcon : viewNotesButton} )} diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/session_view/tabs/alerts_tab.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/session_view/tabs/alerts_tab.tsx index 7bb55d43c5a0b..484287fbab2db 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/session_view/tabs/alerts_tab.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/session_view/tabs/alerts_tab.tsx @@ -25,12 +25,13 @@ import { useSessionViewPanelContext } from '../context'; export const AlertsTab = memo(() => { const { eventId, indexName, investigatedAlertId, sessionEntityId, sessionStartTime, scopeId } = useSessionViewPanelContext(); + const { data: alertsData, fetchNextPage: fetchNextPageAlerts, isFetching: isFetchingAlerts, hasNextPage: hasNextPageAlerts, - } = useFetchSessionViewAlerts(sessionEntityId, sessionStartTime, undefined); + } = useFetchSessionViewAlerts(sessionEntityId, sessionStartTime, investigatedAlertId); // this code mimics what is being done in the x-pack/plugins/session_view/public/components/session_view/index.tsx file const alerts = useMemo(() => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/alert_count_insight.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/alert_count_insight.test.tsx index d9ae4673b1749..711d441c8ba39 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/alert_count_insight.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/alert_count_insight.test.tsx @@ -12,8 +12,16 @@ import { AlertCountInsight, getFormattedAlertStats } from './alert_count_insight import { useAlertsByStatus } from '../../../../overview/components/detection_response/alerts_by_status/use_alerts_by_status'; import type { ParsedAlertsData } from '../../../../overview/components/detection_response/alerts_by_status/types'; import { SEVERITY_COLOR } from '../../../../overview/components/detection_response/utils'; +import { + INSIGHTS_ALERTS_COUNT_INVESTIGATE_IN_TIMELINE_BUTTON_TEST_ID, + INSIGHTS_ALERTS_COUNT_TEXT_TEST_ID, +} from './test_ids'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; +import { useSignalIndex } from '../../../../detections/containers/detection_engine/alerts/use_signal_index'; jest.mock('../../../../common/lib/kibana'); +jest.mock('../../../../detections/containers/detection_engine/alerts/use_signal_index'); +jest.mock('../../../../common/components/user_privileges'); jest.mock('react-router-dom', () => { const actual = jest.requireActual('react-router-dom'); @@ -66,15 +74,42 @@ const renderAlertCountInsight = () => { }; describe('AlertCountInsight', () => { + beforeEach(() => { + (useSignalIndex as jest.Mock).mockReturnValue({ signalIndexName: '' }); + (useUserPrivileges as jest.Mock).mockReturnValue({ timelinePrivileges: { read: true } }); + }); + it('renders', () => { (useAlertsByStatus as jest.Mock).mockReturnValue({ isLoading: false, items: mockAlertData, }); - const { getByTestId } = renderAlertCountInsight(); + + const { getByTestId, queryByTestId } = renderAlertCountInsight(); + expect(getByTestId(testId)).toBeInTheDocument(); expect(getByTestId(`${testId}-distribution-bar`)).toBeInTheDocument(); expect(getByTestId(`${testId}-count`)).toHaveTextContent('8'); + expect( + getByTestId(INSIGHTS_ALERTS_COUNT_INVESTIGATE_IN_TIMELINE_BUTTON_TEST_ID) + ).toBeInTheDocument(); + expect(queryByTestId(INSIGHTS_ALERTS_COUNT_TEXT_TEST_ID)).not.toBeInTheDocument(); + }); + + it('renders the count as text instead of button', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ timelinePrivileges: { read: false } }); + (useAlertsByStatus as jest.Mock).mockReturnValue({ + isLoading: false, + items: mockAlertData, + }); + + const { getByTestId, queryByTestId } = renderAlertCountInsight(); + + expect(getByTestId(`${testId}-count`)).toHaveTextContent('8'); + expect(getByTestId(INSIGHTS_ALERTS_COUNT_TEXT_TEST_ID)).toBeInTheDocument(); + expect( + queryByTestId(INSIGHTS_ALERTS_COUNT_INVESTIGATE_IN_TIMELINE_BUTTON_TEST_ID) + ).not.toBeInTheDocument(); }); it('renders loading spinner if data is being fetched', () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/alert_count_insight.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/alert_count_insight.tsx index 9b5b056311354..77a06132e463c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/alert_count_insight.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/alert_count_insight.tsx @@ -7,7 +7,7 @@ import React, { useMemo } from 'react'; import { capitalize } from 'lodash'; -import { EuiLoadingSpinner, EuiFlexItem, type EuiFlexGroupProps } from '@elastic/eui'; +import { EuiLoadingSpinner, EuiFlexItem, EuiText, type EuiFlexGroupProps } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { InsightDistributionBar } from './insight_distribution_bar'; import { getSeverityColor } from '../../../../detections/components/alerts_kpis/severity_level_panel/helpers'; @@ -26,6 +26,11 @@ import type { AlertsByStatus, ParsedAlertsData, } from '../../../../overview/components/detection_response/alerts_by_status/types'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; +import { + INSIGHTS_ALERTS_COUNT_INVESTIGATE_IN_TIMELINE_BUTTON_TEST_ID, + INSIGHTS_ALERTS_COUNT_TEXT_TEST_ID, +} from './test_ids'; interface AlertCountInsightProps { /** @@ -82,6 +87,10 @@ export const AlertCountInsight: React.FC = ({ direction, 'data-test-subj': dataTestSubj, }) => { + const { + timelinePrivileges: { read: canUseTimeline }, + } = useUserPrivileges(); + const entityFilter = useMemo(() => ({ field: fieldName, value: name }), [fieldName, name]); const { to, from } = useGlobalTime(); const { signalIndexName } = useSignalIndex(); @@ -119,6 +128,29 @@ export const AlertCountInsight: React.FC = ({ [fieldName, name] ); + // renders either a button to open timeline or just plain text depending on the user's timeline privileges + const alertCount = useMemo(() => { + const formattedAlertCount = ; + + if (!canUseTimeline) { + return ( + + {formattedAlertCount} + + ); + } + return ( + + {formattedAlertCount} + + ); + }, [canUseTimeline, dataProviders, totalAlertCount]); + if (!isLoading && totalAlertCount === 0) return null; return ( @@ -134,17 +166,7 @@ export const AlertCountInsight: React.FC = ({ /> } stats={alertStats} - count={ -
- - - -
- } + count={
{alertCount}
} direction={direction} data-test-subj={`${dataTestSubj}-distribution-bar`} /> diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/take_action_dropdown.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/take_action_dropdown.test.tsx index ffed3e064d7f5..d862c6c09e62b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/take_action_dropdown.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/take_action_dropdown.test.tsx @@ -108,7 +108,7 @@ describe('take action dropdown', () => { isOsqueryAvailable: jest.fn().mockReturnValue(true), }, application: { - capabilities: { siem: { crud_alerts: true, read_alerts: true }, osquery: true }, + capabilities: { siemV2: { crud_alerts: true, read_alerts: true }, osquery: true }, }, }, }; @@ -147,6 +147,10 @@ describe('take action dropdown', () => { let wrapper: ReactWrapper; beforeAll(() => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + ...getUserPrivilegesMockDefaultValue(), + timelinePrivileges: { read: true }, + }); wrapper = mount( @@ -246,6 +250,29 @@ describe('take action dropdown', () => { }); }); + describe('privileges', () => { + test('should not render "Investigate in timeline" when the user does not have timeline privileges', async () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + ...getUserPrivilegesMockDefaultValue(), + timelinePrivileges: { read: false }, + }); + const wrapper = mount( + + + + ); + wrapper + .find(`button[data-test-subj="${FLYOUT_FOOTER_DROPDOWN_BUTTON_TEST_ID}"]`) + .simulate('click'); + + await waitFor(() => { + expect( + wrapper.exists('[data-test-subj="investigate-in-timeline-action-item"]') + ).toBeFalsy(); + }); + }); + }); + describe('for Endpoint related actions', () => { /** Removes the detail data that is used to determine if data is for an Alert */ const setAlertDetailsDataMockToEvent = () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/test_ids.ts b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/test_ids.ts index 5895386d43dc1..0cc556ca4d01c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/test_ids.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/test_ids.ts @@ -12,7 +12,9 @@ export const FLYOUT_PREVIEW_LINK_TEST_ID = `${PREFIX}PreviewLink` as const; export const SESSION_VIEW_UPSELL_TEST_ID = `${PREFIX}SessionViewUpsell` as const; export const SESSION_VIEW_NO_DATA_TEST_ID = `${PREFIX}SessionViewNoData` as const; -export const MISCONFIGURATIONS_TEST_ID = `${PREFIX}Misconfigurations` as const; -export const VULNERABILITIES_TEST_ID = `${PREFIX}Vulnerabilities` as const; +const INSIGHTS_TEST_ID = `${PREFIX}Insights` as const; +export const INSIGHTS_ALERTS_COUNT_TEXT_TEST_ID = `${INSIGHTS_TEST_ID}AlertsCount` as const; +export const INSIGHTS_ALERTS_COUNT_INVESTIGATE_IN_TIMELINE_BUTTON_TEST_ID = + `${INSIGHTS_TEST_ID}AlertsCountInvestigateInTimelineButton` as const; export const FLYOUT_FOOTER_DROPDOWN_BUTTON_TEST_ID = `${PREFIX}FooterDropdownButton` as const; diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/vulnerabilities_insight.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/vulnerabilities_insight.tsx index 125e7e9985edb..748deea7105ef 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/vulnerabilities_insight.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/vulnerabilities_insight.tsx @@ -10,6 +10,7 @@ import { EuiFlexItem, type EuiFlexGroupProps, useEuiTheme } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { css } from '@emotion/react'; import { useVulnerabilitiesPreview } from '@kbn/cloud-security-posture/src/hooks/use_vulnerabilities_preview'; +import { useGetSeverityStatusColor } from '@kbn/cloud-security-posture/src/hooks/use_get_severity_status_color'; import { buildGenericEntityFlyoutPreviewQuery } from '@kbn/cloud-security-posture-common'; import { getVulnerabilityStats, hasVulnerabilitiesData } from '@kbn/cloud-security-posture'; import { @@ -52,6 +53,7 @@ export const VulnerabilitiesInsight: React.FC = ({ }) => { const { scopeId, isPreview } = useDocumentDetailsContext(); const { euiTheme } = useEuiTheme(); + const { getSeverityStatusColor } = useGetSeverityStatusColor(); const { data } = useVulnerabilitiesPreview({ query: buildGenericEntityFlyoutPreviewQuery('host.name', hostName), sort: [], @@ -87,14 +89,17 @@ export const VulnerabilitiesInsight: React.FC = ({ const vulnerabilitiesStats = useMemo( () => - getVulnerabilityStats({ - critical: CRITICAL, - high: HIGH, - medium: MEDIUM, - low: LOW, - none: NONE, - }), - [CRITICAL, HIGH, MEDIUM, LOW, NONE] + getVulnerabilityStats( + { + critical: CRITICAL, + high: HIGH, + medium: MEDIUM, + low: LOW, + none: NONE, + }, + getSeverityStatusColor + ), + [CRITICAL, HIGH, MEDIUM, LOW, NONE, getSeverityStatusColor] ); const count = useMemo( diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/host_details_left/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/host_details_left/index.tsx index 7a9b74b238ea4..b40483083f9af 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/host_details_left/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/host_details_left/index.tsx @@ -7,7 +7,7 @@ import React, { useMemo, useState } from 'react'; import type { FlyoutPanelProps } from '@kbn/expandable-flyout'; -import { EntityType } from '../../../../common/entity_analytics/types'; +import { EntityIdentifierFields, EntityType } from '../../../../common/entity_analytics/types'; import { getRiskInputTab, getInsightsInputTab, @@ -61,7 +61,7 @@ export const HostDetailsPanel = ({ // Determine if the Insights tab should be included const insightsTab = hasMisconfigurationFindings || hasVulnerabilitiesFindings || hasNonClosedAlerts - ? [getInsightsInputTab({ name, fieldName: 'host.name' })] + ? [getInsightsInputTab({ name, fieldName: EntityIdentifierFields.hostName })] : []; return [[...riskScoreTab, ...insightsTab], EntityDetailsLeftPanelTab.RISK_INPUTS, () => {}]; }, [ diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/host_right/content.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/host_right/content.tsx index d62e1bf016b45..92d40aa49d676 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/host_right/content.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/host_right/content.tsx @@ -12,7 +12,7 @@ import { EntityInsight } from '../../../cloud_security_posture/components/entity import { AssetCriticalityAccordion } from '../../../entity_analytics/components/asset_criticality/asset_criticality_selector'; import { FlyoutRiskSummary } from '../../../entity_analytics/components/risk_summary_flyout/risk_summary'; import type { RiskScoreState } from '../../../entity_analytics/api/hooks/use_risk_score'; -import { EntityType } from '../../../../common/entity_analytics/types'; +import { EntityIdentifierFields, EntityType } from '../../../../common/entity_analytics/types'; import type { HostItem } from '../../../../common/search_strategy'; import { ObservedEntity } from '../shared/components/observed_entity'; import { HOST_PANEL_OBSERVED_HOST_QUERY_ID, HOST_PANEL_RISK_SCORE_QUERY_ID } from '.'; @@ -66,12 +66,12 @@ export const HostPanelContent = ({ )} { contextID: string; @@ -98,7 +98,7 @@ export const HostPanel = ({ const { hasVulnerabilitiesFindings } = useHasVulnerabilities('host.name', hostName); const { hasNonClosedAlerts } = useNonClosedAlerts({ - field: 'host.name', + field: EntityIdentifierFields.hostName, value: hostName, to, from, diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/mocks/index.ts b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/mocks/index.ts index 4ef82dbf426ad..2865d4a388b19 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/mocks/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/mocks/index.ts @@ -13,6 +13,7 @@ import type { HostRiskScore, EntityType, UserRiskScore, + ServiceRiskScore, } from '../../../../common/search_strategy'; import { HostPolicyResponseActionStatus, RiskSeverity } from '../../../../common/search_strategy'; import { RiskCategories } from '../../../../common/entity_analytics/risk_engine'; @@ -86,6 +87,40 @@ const hostRiskScore: HostRiskScore = { oldestAlertTimestamp: '1989-11-08T23:00:00.000Z', }; +const serviceRiskScore: ServiceRiskScore = { + '@timestamp': '1989-11-08T23:00:00.000Z', + service: { + name: 'test', + risk: { + rule_risks: [], + calculated_score_norm: 70, + multipliers: [], + calculated_level: RiskSeverity.High, + '@timestamp': '', + id_field: '', + id_value: '', + calculated_score: 0, + category_1_count: 5, + category_1_score: 20, + category_2_count: 1, + category_2_score: 10, + notes: [], + inputs: [ + { + id: '_id', + index: '_index', + category: RiskCategories.category_1, + description: 'Alert from Rule: My rule', + risk_score: 30, + timestamp: '2021-08-19T18:55:59.000Z', + }, + ], + }, + }, + alertsCount: 0, + oldestAlertTimestamp: '1989-11-08T23:00:00.000Z', +}; + export const mockUserRiskScoreState: RiskScoreState = { data: [userRiskScore], inspect: { @@ -116,6 +151,21 @@ export const mockHostRiskScoreState: RiskScoreState = { error: undefined, }; +export const mockServiceRiskScoreState: RiskScoreState = { + data: [serviceRiskScore], + inspect: { + dsl: [], + response: [], + }, + isInspected: false, + refetch: () => {}, + totalCount: 0, + isAuthorized: true, + hasEngineBeenInstalled: true, + loading: false, + error: undefined, +}; + const hostMetadata: HostMetadataInterface = { '@timestamp': 1036358673463478, diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_details_left/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_details_left/index.test.tsx new file mode 100644 index 0000000000000..97817d4d14afd --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_details_left/index.test.tsx @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TestProviders } from '../../../common/mock'; +import { render } from '@testing-library/react'; +import React from 'react'; +import { ServiceDetailsPanel } from '.'; +import { EntityDetailsLeftPanelTab } from '../shared/components/left_panel/left_panel_header'; + +describe('LeftPanel', () => { + it('renders', () => { + const { queryByText } = render( + , + { + wrapper: TestProviders, + } + ); + + const tabElement = queryByText('Risk contributions'); + + expect(tabElement).toBeInTheDocument(); + }); + + it('does not render the tab if tab is not found', () => { + const { queryByText } = render( + , + { + wrapper: TestProviders, + } + ); + + const tabElement = queryByText('Risk Inputs'); + + expect(tabElement).not.toBeInTheDocument(); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_details_left/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_details_left/index.tsx new file mode 100644 index 0000000000000..ef9cb55029b10 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_details_left/index.tsx @@ -0,0 +1,93 @@ +/* + * 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, { useMemo } from 'react'; +import type { FlyoutPanelProps, PanelPath } from '@kbn/expandable-flyout'; +import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { useTabs } from './tabs'; +import type { + EntityDetailsLeftPanelTab, + LeftPanelTabsType, +} from '../shared/components/left_panel/left_panel_header'; +import { LeftPanelHeader } from '../shared/components/left_panel/left_panel_header'; +import { LeftPanelContent } from '../shared/components/left_panel/left_panel_content'; + +interface ServiceParam { + name: string; + email: string[]; +} + +export interface ServiceDetailsPanelProps extends Record { + isRiskScoreExist: boolean; + service: ServiceParam; + path?: PanelPath; + scopeId: string; +} +export interface ServiceDetailsExpandableFlyoutProps extends FlyoutPanelProps { + key: 'service_details'; + params: ServiceDetailsPanelProps; +} +export const ServiceDetailsPanelKey: ServiceDetailsExpandableFlyoutProps['key'] = 'service_details'; + +export const ServiceDetailsPanel = ({ + isRiskScoreExist, + service, + path, + scopeId, +}: ServiceDetailsPanelProps) => { + const tabs = useTabs(service.name, scopeId); + + const { selectedTabId, setSelectedTabId } = useSelectedTab(isRiskScoreExist, service, tabs, path); + + if (!selectedTabId) { + return null; + } + + return ( + <> + + + + ); +}; + +const useSelectedTab = ( + isRiskScoreExist: boolean, + service: ServiceParam, + tabs: LeftPanelTabsType, + path: PanelPath | undefined +) => { + const { openLeftPanel } = useExpandableFlyoutApi(); + + const selectedTabId = useMemo(() => { + const defaultTab = tabs.length > 0 ? tabs[0].id : undefined; + if (!path) return defaultTab; + + return tabs.find((tab) => tab.id === path.tab)?.id ?? defaultTab; + }, [path, tabs]); + + const setSelectedTabId = (tabId: EntityDetailsLeftPanelTab) => { + openLeftPanel({ + id: ServiceDetailsPanelKey, + params: { + service, + isRiskScoreExist, + path: { + tab: tabId, + }, + }, + }); + }; + + return { setSelectedTabId, selectedTabId }; +}; + +ServiceDetailsPanel.displayName = 'ServiceDetailsPanel'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_details_left/tabs.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_details_left/tabs.tsx new file mode 100644 index 0000000000000..b8ebe2cffeabc --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_details_left/tabs.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 { useMemo } from 'react'; +import { getRiskInputTab } from '../../../entity_analytics/components/entity_details_flyout'; +import { EntityType } from '../../../../common/entity_analytics/types'; +import type { LeftPanelTabsType } from '../shared/components/left_panel/left_panel_header'; + +export const useTabs = (name: string, scopeId: string): LeftPanelTabsType => + useMemo(() => { + return [ + getRiskInputTab({ + entityName: name, + entityType: EntityType.service, + scopeId, + }), + ]; + }, [name, scopeId]); diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/content.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/content.tsx new file mode 100644 index 0000000000000..8c8d25ae8685b --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/content.tsx @@ -0,0 +1,85 @@ +/* + * 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 { EuiHorizontalRule } from '@elastic/eui'; + +import React from 'react'; +import type { ServiceItem } from '../../../../common/search_strategy'; +import { AssetCriticalityAccordion } from '../../../entity_analytics/components/asset_criticality/asset_criticality_selector'; +import { FlyoutRiskSummary } from '../../../entity_analytics/components/risk_summary_flyout/risk_summary'; +import type { RiskScoreState } from '../../../entity_analytics/api/hooks/use_risk_score'; +import { EntityType } from '../../../../common/entity_analytics/types'; +import { SERVICE_PANEL_RISK_SCORE_QUERY_ID } from '.'; +import { FlyoutBody } from '../../shared/components/flyout_body'; +import { ObservedEntity } from '../shared/components/observed_entity'; +import type { ObservedEntityData } from '../shared/components/observed_entity/types'; +import { useObservedServiceItems } from './hooks/use_observed_service_items'; +import type { EntityDetailsPath } from '../shared/components/left_panel/left_panel_header'; + +export const OBSERVED_SERVICE_QUERY_ID = 'observedServiceDetailsQuery'; + +interface ServicePanelContentProps { + serviceName: string; + observedService: ObservedEntityData; + riskScoreState: RiskScoreState; + recalculatingScore: boolean; + contextID: string; + scopeId: string; + isDraggable: boolean; + onAssetCriticalityChange: () => void; + openDetailsPanel: (path: EntityDetailsPath) => void; + isPreviewMode?: boolean; + isLinkEnabled: boolean; +} + +export const ServicePanelContent = ({ + serviceName, + observedService, + riskScoreState, + recalculatingScore, + contextID, + scopeId, + isDraggable, + openDetailsPanel, + onAssetCriticalityChange, + isPreviewMode, + isLinkEnabled, +}: ServicePanelContentProps) => { + const observedFields = useObservedServiceItems(observedService); + + return ( + + {riskScoreState.hasEngineBeenInstalled && riskScoreState.data?.length !== 0 && ( + <> + + + + )} + + + + + ); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/header.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/header.test.tsx new file mode 100644 index 0000000000000..fcd6976c58d23 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/header.test.tsx @@ -0,0 +1,62 @@ +/* + * 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 { TestProviders } from '../../../common/mock'; +import { ServicePanelHeader } from './header'; +import { mockObservedService } from './mocks'; + +const mockProps = { + serviceName: 'test', + observedService: mockObservedService, +}; + +jest.mock('../../../common/components/visualization_actions/visualization_embeddable'); + +describe('ServicePanelHeader', () => { + it('renders', () => { + const { getByTestId } = render( + + + + ); + + expect(getByTestId('service-panel-header')).toBeInTheDocument(); + }); + + it('renders observed badge when lastSeen is defined', () => { + const { getByTestId } = render( + + + + ); + + expect(getByTestId('service-panel-header-observed-badge')).toBeInTheDocument(); + }); + + it('does not render observed badge when lastSeen date is undefined', () => { + const { queryByTestId } = render( + + + + ); + + expect(queryByTestId('service-panel-header-observed-badge')).not.toBeInTheDocument(); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/header.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/header.tsx new file mode 100644 index 0000000000000..9636b6f3f760a --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/header.tsx @@ -0,0 +1,60 @@ +/* + * 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 { EuiSpacer, EuiBadge, EuiText, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import React, { useMemo } from 'react'; + +import { EntityType } from '../../../../common/search_strategy'; +import { EntityIconByType } from '../../../entity_analytics/components/entity_store/helpers'; +import type { ServiceItem } from '../../../../common/search_strategy/security_solution/services/common'; +import { PreferenceFormattedDate } from '../../../common/components/formatted_date'; +import { FlyoutHeader } from '../../shared/components/flyout_header'; +import { FlyoutTitle } from '../../shared/components/flyout_title'; +import type { ObservedEntityData } from '../shared/components/observed_entity/types'; + +interface ServicePanelHeaderProps { + serviceName: string; + observedService: ObservedEntityData; +} + +export const ServicePanelHeader = ({ serviceName, observedService }: ServicePanelHeaderProps) => { + const lastSeenDate = useMemo( + () => observedService.lastSeen.date && new Date(observedService.lastSeen.date), + [observedService.lastSeen] + ); + + return ( + + + + + {lastSeenDate && } + + + + + + + + + + {observedService.lastSeen.date && ( + + + + )} + + + + + + ); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/observed_service_details.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/observed_service_details.test.tsx new file mode 100644 index 0000000000000..836f25eb3d36f --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/observed_service_details.test.tsx @@ -0,0 +1,72 @@ +/* + * 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 { useObservedUserDetails } from '../../../../explore/users/containers/users/observed_details'; +import { TestProviders } from '../../../../common/mock'; +import { renderHook, act } from '@testing-library/react'; +import { useSearchStrategy } from '../../../../common/containers/use_search_strategy'; + +jest.mock('../../../../common/containers/use_search_strategy', () => ({ + useSearchStrategy: jest.fn(), +})); +const mockUseSearchStrategy = useSearchStrategy as jest.Mock; +const mockSearch = jest.fn(); + +const defaultProps = { + endDate: '2020-07-08T08:20:18.966Z', + indexNames: ['fakebeat-*'], + skip: false, + startDate: '2020-07-07T08:20:18.966Z', + userName: 'myUserName', +}; + +describe('useUserDetails', () => { + beforeEach(() => { + jest.clearAllMocks(); + mockUseSearchStrategy.mockReturnValue({ + loading: false, + result: { + overviewNetwork: {}, + }, + search: mockSearch, + refetch: jest.fn(), + inspect: {}, + }); + }); + + it('runs search', () => { + renderHook(() => useObservedUserDetails(defaultProps), { + wrapper: TestProviders, + }); + + expect(mockSearch).toHaveBeenCalled(); + }); + + it('does not run search when skip = true', () => { + const props = { + ...defaultProps, + skip: true, + }; + renderHook(() => useObservedUserDetails(props), { + wrapper: TestProviders, + }); + + expect(mockSearch).not.toHaveBeenCalled(); + }); + it('skip = true will cancel any running request', () => { + const props = { + ...defaultProps, + }; + const { rerender } = renderHook(() => useObservedUserDetails(props), { + wrapper: TestProviders, + }); + props.skip = true; + act(() => rerender()); + expect(mockUseSearchStrategy).toHaveBeenCalledTimes(2); + expect(mockUseSearchStrategy.mock.calls[1][0].abort).toEqual(true); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/observed_service_details.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/observed_service_details.tsx new file mode 100644 index 0000000000000..04df328e8b357 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/observed_service_details.tsx @@ -0,0 +1,93 @@ +/* + * 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 { useEffect, useMemo } from 'react'; +import { i18n } from '@kbn/i18n'; +import { useSearchStrategy } from '../../../../common/containers/use_search_strategy'; +import type { inputsModel } from '../../../../common/store'; +import type { InspectResponse } from '../../../../types'; +import { ServicesQueries } from '../../../../../common/search_strategy/security_solution/services'; +import type { ServiceItem } from '../../../../../common/search_strategy/security_solution/services/common'; +import { OBSERVED_SERVICE_QUERY_ID } from '../content'; + +export interface ServiceDetailsArgs { + id: string; + inspect: InspectResponse; + serviceDetails: ServiceItem; + refetch: inputsModel.Refetch; + startDate: string; + endDate: string; +} + +interface UseServiceDetails { + endDate: string; + serviceName: string; + id?: string; + indexNames: string[]; + skip?: boolean; + startDate: string; +} + +export const useObservedServiceDetails = ({ + endDate, + serviceName, + indexNames, + id = OBSERVED_SERVICE_QUERY_ID, + skip = false, + startDate, +}: UseServiceDetails): [boolean, ServiceDetailsArgs] => { + const { + loading, + result: response, + search, + refetch, + inspect, + } = useSearchStrategy({ + factoryQueryType: ServicesQueries.observedDetails, + initialResult: { + serviceDetails: {}, + }, + errorMessage: i18n.translate('xpack.securitySolution.serviceDetails.failSearchDescription', { + defaultMessage: `Failed to run search on service details`, + }), + abort: skip, + }); + + const serviceDetailsResponse = useMemo( + () => ({ + endDate, + serviceDetails: response.serviceDetails, + id, + inspect, + refetch, + startDate, + }), + [endDate, id, inspect, refetch, response.serviceDetails, startDate] + ); + + const serviceDetailsRequest = useMemo( + () => ({ + defaultIndex: indexNames, + factoryQueryType: ServicesQueries.observedDetails, + serviceName, + timerange: { + interval: '12h', + from: startDate, + to: endDate, + }, + }), + [endDate, indexNames, startDate, serviceName] + ); + + useEffect(() => { + if (!skip) { + search(serviceDetailsRequest); + } + }, [serviceDetailsRequest, search, skip]); + + return [loading, serviceDetailsResponse]; +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/translations.ts new file mode 100644 index 0000000000000..1591a93a9cfbb --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/translations.ts @@ -0,0 +1,99 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const SERVICE_ID = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.service.idLabel', + { + defaultMessage: 'Service ID', + } +); + +export const SERVICE_NAME = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.service.nameLabel', + { + defaultMessage: 'Name', + } +); + +export const FIRST_SEEN = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.service.firstSeenLabel', + { + defaultMessage: 'First seen', + } +); + +export const LAST_SEEN = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.service.lastSeenLabel', + { + defaultMessage: 'Last seen', + } +); + +export const ADDRESS = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.service.addressLabel', + { + defaultMessage: 'Address', + } +); + +export const ENVIRONMENT = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.service.environmentLabel', + { + defaultMessage: 'Environment', + } +); + +export const EPHEMERAL_ID = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.service.ephemeralIdLabel', + { + defaultMessage: 'Ephemeral ID', + } +); + +export const NODE_NAME = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.service.nodeNameLabel', + { + defaultMessage: 'Node name', + } +); + +export const NODE_ROLES = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.service.nodeRolesLabel', + { + defaultMessage: 'Node roles', + } +); + +export const NODE_ROLE = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.service.nodeRoleLabel', + { + defaultMessage: 'Node role', + } +); + +export const STATE = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.service.stateLabel', + { + defaultMessage: 'State', + } +); + +export const TYPE = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.service.typeLabel', + { + defaultMessage: 'Type', + } +); + +export const VERSION = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.service.versionLabel', + { + defaultMessage: 'Version', + } +); diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/use_navigate_to_service_details.test.ts b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/use_navigate_to_service_details.test.ts new file mode 100644 index 0000000000000..5299445cefc91 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/use_navigate_to_service_details.test.ts @@ -0,0 +1,163 @@ +/* + * 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'; +import { useNavigateToServiceDetails } from './use_navigate_to_service_details'; +import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; +import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { + CspInsightLeftPanelSubTab, + EntityDetailsLeftPanelTab, +} from '../../shared/components/left_panel/left_panel_header'; +import { ServiceDetailsPanelKey } from '../../service_details_left'; +import { createTelemetryServiceMock } from '../../../../common/lib/telemetry/telemetry_service.mock'; +import { ServicePanelKey } from '../../shared/constants'; + +jest.mock('@kbn/expandable-flyout'); +jest.mock('../../../../common/hooks/use_experimental_features'); + +const mockedTelemetry = createTelemetryServiceMock(); +jest.mock('../../../../common/lib/kibana', () => { + const original = jest.requireActual('../../../../common/lib/kibana'); + return { + ...original, + useKibana: () => ({ + ...original.useKibana(), + services: { + ...original.useKibana().services, + telemetry: mockedTelemetry, + }, + }), + }; +}); + +const mockProps = { + serviceName: 'testService', + scopeId: 'testScopeId', + isRiskScoreExist: false, + hasMisconfigurationFindings: false, + hasNonClosedAlerts: false, + contextID: 'testContextID', + isPreviewMode: false, + email: ['test@test.com'], +}; + +const tab = EntityDetailsLeftPanelTab.RISK_INPUTS; +const subTab = CspInsightLeftPanelSubTab.MISCONFIGURATIONS; + +const mockOpenLeftPanel = jest.fn(); +const mockOpenFlyout = jest.fn(); + +describe('useNavigateToServiceDetails', () => { + describe('when preview navigation is enabled', () => { + beforeEach(() => { + jest.clearAllMocks(); + (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(true); + (useExpandableFlyoutApi as jest.Mock).mockReturnValue({ + openLeftPanel: mockOpenLeftPanel, + openFlyout: mockOpenFlyout, + }); + }); + + it('returns callback that opens details panel when not in preview mode', () => { + const { result } = renderHook(() => useNavigateToServiceDetails(mockProps)); + + expect(result.current.isLinkEnabled).toBe(true); + result.current.openDetailsPanel({ tab, subTab }); + + expect(result.current.isLinkEnabled).toBe(true); + result.current.openDetailsPanel({ tab, subTab }); + + expect(mockOpenLeftPanel).toHaveBeenCalledWith({ + id: ServiceDetailsPanelKey, + params: { + service: { + name: mockProps.serviceName, + }, + scopeId: mockProps.scopeId, + isRiskScoreExist: mockProps.isRiskScoreExist, + path: { tab, subTab }, + }, + }); + }); + + it('returns callback that opens flyout when in preview mode', () => { + const { result } = renderHook(() => + useNavigateToServiceDetails({ ...mockProps, isPreviewMode: true }) + ); + + expect(result.current.isLinkEnabled).toBe(true); + result.current.openDetailsPanel({ tab, subTab }); + + expect(mockOpenFlyout).toHaveBeenCalledWith({ + right: { + id: ServicePanelKey, + params: { + contextID: mockProps.contextID, + scopeId: mockProps.scopeId, + serviceName: mockProps.serviceName, + }, + }, + left: { + id: ServiceDetailsPanelKey, + params: { + service: { + name: mockProps.serviceName, + }, + scopeId: mockProps.scopeId, + isRiskScoreExist: mockProps.isRiskScoreExist, + path: { tab, subTab }, + }, + }, + }); + expect(mockOpenLeftPanel).not.toHaveBeenCalled(); + }); + }); + + describe('when preview navigation is disabled', () => { + beforeEach(() => { + jest.clearAllMocks(); + (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(false); + (useExpandableFlyoutApi as jest.Mock).mockReturnValue({ + openLeftPanel: mockOpenLeftPanel, + openFlyout: mockOpenFlyout, + }); + }); + + it('returns callback that opens details panel when not in preview mode', () => { + const { result } = renderHook(() => useNavigateToServiceDetails(mockProps)); + + expect(result.current.isLinkEnabled).toBe(true); + result.current.openDetailsPanel({ tab, subTab }); + + expect(mockOpenLeftPanel).toHaveBeenCalledWith({ + id: ServiceDetailsPanelKey, + params: { + service: { + name: mockProps.serviceName, + }, + scopeId: mockProps.scopeId, + isRiskScoreExist: mockProps.isRiskScoreExist, + path: { tab, subTab }, + }, + }); + expect(mockOpenFlyout).not.toHaveBeenCalled(); + }); + + it('returns empty callback and isLinkEnabled is false when in preview mode', () => { + const { result } = renderHook(() => + useNavigateToServiceDetails({ ...mockProps, isPreviewMode: true }) + ); + + expect(result.current.isLinkEnabled).toBe(false); + result.current.openDetailsPanel({ tab, subTab }); + + expect(mockOpenLeftPanel).not.toHaveBeenCalled(); + expect(mockOpenFlyout).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/use_navigate_to_service_details.ts b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/use_navigate_to_service_details.ts new file mode 100644 index 0000000000000..a8ec9fb80624a --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/use_navigate_to_service_details.ts @@ -0,0 +1,105 @@ +/* + * 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 { useCallback } from 'react'; +import { EntityType } from '../../../../../common/search_strategy'; +import type { EntityDetailsPath } from '../../shared/components/left_panel/left_panel_header'; +import { useKibana } from '../../../../common/lib/kibana'; +import { EntityEventTypes } from '../../../../common/lib/telemetry'; +import { ServiceDetailsPanelKey } from '../../service_details_left'; +import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; +import { ServicePanelKey } from '../../shared/constants'; + +interface UseNavigateToServiceDetailsParams { + serviceName: string; + email?: string[]; + scopeId: string; + contextID: string; + isDraggable?: boolean; + isRiskScoreExist: boolean; + isPreviewMode?: boolean; +} + +interface UseNavigateToServiceDetailsResult { + /** + * Opens the service details panel + */ + openDetailsPanel: (path: EntityDetailsPath) => void; + /** + * Whether the link is enabled + */ + isLinkEnabled: boolean; +} + +export const useNavigateToServiceDetails = ({ + serviceName, + scopeId, + contextID, + isDraggable, + isRiskScoreExist, + isPreviewMode, +}: UseNavigateToServiceDetailsParams): UseNavigateToServiceDetailsResult => { + const { telemetry } = useKibana().services; + const { openLeftPanel, openFlyout } = useExpandableFlyoutApi(); + const isNewNavigationEnabled = useIsExperimentalFeatureEnabled( + 'newExpandableFlyoutNavigationEnabled' + ); + + const isLinkEnabled = !isPreviewMode || (isNewNavigationEnabled && isPreviewMode); + + const openDetailsPanel = useCallback( + (path: EntityDetailsPath) => { + telemetry.reportEvent(EntityEventTypes.RiskInputsExpandedFlyoutOpened, { + entity: EntityType.service, + }); + + const left = { + id: ServiceDetailsPanelKey, + params: { + isRiskScoreExist, + scopeId, + service: { + name: serviceName, + }, + path, + }, + }; + + const right = { + id: ServicePanelKey, + params: { + contextID, + serviceName, + scopeId, + isDraggable, + }, + }; + + // When new navigation is enabled, navigation in preview is enabled and open a new flyout + if (isNewNavigationEnabled && isPreviewMode) { + openFlyout({ right, left }); + } else if (!isPreviewMode) { + // When not in preview mode, open left panel as usual + openLeftPanel(left); + } + }, + [ + contextID, + isDraggable, + isNewNavigationEnabled, + isPreviewMode, + isRiskScoreExist, + openFlyout, + openLeftPanel, + scopeId, + serviceName, + telemetry, + ] + ); + + return { openDetailsPanel, isLinkEnabled }; +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/use_observed_service.ts b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/use_observed_service.ts new file mode 100644 index 0000000000000..8a71dd3f20f44 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/use_observed_service.ts @@ -0,0 +1,90 @@ +/* + * 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 { useMemo } from 'react'; +import { useDeepEqualSelector } from '../../../../common/hooks/use_selector'; +import { inputsSelectors } from '../../../../common/store'; +import { useQueryInspector } from '../../../../common/components/page/manage_query'; +import type { ObservedEntityData } from '../../shared/components/observed_entity/types'; +import type { ServiceItem } from '../../../../../common/search_strategy'; +import { Direction, NOT_EVENT_KIND_ASSET_FILTER } from '../../../../../common/search_strategy'; +import { useGlobalTime } from '../../../../common/containers/use_global_time'; +import { useFirstLastSeen } from '../../../../common/containers/use_first_last_seen'; +import { isActiveTimeline } from '../../../../helpers'; +import { useTimelineDataFilters } from '../../../../timelines/containers/use_timeline_data_filters'; +import { useObservedServiceDetails } from './observed_service_details'; + +export const useObservedService = ( + serviceName: string, + scopeId: string +): Omit, 'anomalies'> => { + const timelineTime = useDeepEqualSelector((state) => + inputsSelectors.timelineTimeRangeSelector(state) + ); + const globalTime = useGlobalTime(); + const isActiveTimelines = isActiveTimeline(scopeId); + const { to, from } = isActiveTimelines ? timelineTime : globalTime; + const { isInitializing, setQuery, deleteQuery } = globalTime; + + const { selectedPatterns } = useTimelineDataFilters(isActiveTimeline(scopeId)); + + const [ + loadingObservedService, + { serviceDetails: observedServiceDetails, inspect, refetch, id: queryId }, + ] = useObservedServiceDetails({ + endDate: to, + startDate: from, + serviceName, + indexNames: selectedPatterns, + skip: isInitializing, + }); + + useQueryInspector({ + deleteQuery, + inspect, + refetch, + setQuery, + queryId, + loading: loadingObservedService, + }); + + const [loadingFirstSeen, { firstSeen }] = useFirstLastSeen({ + field: 'service.name', + value: serviceName, + defaultIndex: selectedPatterns, + order: Direction.asc, + filterQuery: NOT_EVENT_KIND_ASSET_FILTER, + }); + + const [loadingLastSeen, { lastSeen }] = useFirstLastSeen({ + field: 'service.name', + value: serviceName, + defaultIndex: selectedPatterns, + order: Direction.desc, + filterQuery: NOT_EVENT_KIND_ASSET_FILTER, + }); + + return useMemo( + () => ({ + details: observedServiceDetails, + isLoading: loadingObservedService || loadingLastSeen || loadingFirstSeen, + firstSeen: { + date: firstSeen, + isLoading: loadingFirstSeen, + }, + lastSeen: { date: lastSeen, isLoading: loadingLastSeen }, + }), + [ + firstSeen, + lastSeen, + loadingFirstSeen, + loadingLastSeen, + loadingObservedService, + observedServiceDetails, + ] + ); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/use_observed_service_items.test.ts b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/use_observed_service_items.test.ts new file mode 100644 index 0000000000000..9fe230be0f952 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/use_observed_service_items.test.ts @@ -0,0 +1,103 @@ +/* + * 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'; +import { mockObservedService } from '../mocks'; +import { TestProviders } from '../../../../common/mock'; +import { useObservedServiceItems } from './use_observed_service_items'; + +describe('useObservedServiceItems', () => { + it('returns observed service fields', () => { + const { result } = renderHook(() => useObservedServiceItems(mockObservedService), { + wrapper: TestProviders, + }); + + expect(result.current).toEqual([ + { + field: 'service.id', + label: 'Service ID', + getValues: expect.any(Function), + }, + { + field: 'service.name', + getValues: expect.any(Function), + label: 'Name', + }, + { + field: 'service.address', + getValues: expect.any(Function), + label: 'Address', + }, + { + field: 'service.environment', + getValues: expect.any(Function), + label: 'Environment', + }, + { + field: 'service.ephemeral_id', + getValues: expect.any(Function), + label: 'Ephemeral ID', + }, + { + field: 'service.node.name', + getValues: expect.any(Function), + label: 'Node name', + }, + { + field: 'service.node.roles', + getValues: expect.any(Function), + label: 'Node roles', + }, + { + field: 'service.node.role', + getValues: expect.any(Function), + label: 'Node role', + }, + { + field: 'service.state', + getValues: expect.any(Function), + label: 'State', + }, + { + field: 'service.type', + getValues: expect.any(Function), + label: 'Type', + }, + { + field: 'service.version', + getValues: expect.any(Function), + label: 'Version', + }, + { + label: 'First seen', + render: expect.any(Function), + }, + { + label: 'Last seen', + render: expect.any(Function), + }, + ]); + + expect( + result.current.map(({ getValues }) => getValues && getValues(mockObservedService)) + ).toEqual([ + ['test id'], // id + ['test name', 'another test name'], // name + ['test address'], // address + ['test environment'], // environment + ['test ephemeral_id'], // ephemeral_id + ['test node name'], // node name + ['test node roles'], // node roles + ['test node role'], // node roles + ['test state'], // state + ['test type'], // type + ['test version'], // version + undefined, + undefined, + ]); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/use_observed_service_items.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/use_observed_service_items.tsx new file mode 100644 index 0000000000000..6a994cefb6a36 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/hooks/use_observed_service_items.tsx @@ -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 React from 'react'; +import type { ServiceItem } from '../../../../../common/search_strategy'; +import { FormattedRelativePreferenceDate } from '../../../../common/components/formatted_date'; +import * as i18n from './translations'; +import type { ObservedEntityData } from '../../shared/components/observed_entity/types'; +import type { EntityTableRows } from '../../shared/components/entity_table/types'; +import { getEmptyTagValue } from '../../../../common/components/empty_value'; + +const basicServiceFields: EntityTableRows> = [ + { + label: i18n.SERVICE_ID, + getValues: (serviceData: ObservedEntityData) => serviceData.details.service?.id, + field: 'service.id', + }, + { + label: i18n.SERVICE_NAME, + getValues: (serviceData: ObservedEntityData) => serviceData.details.service?.name, + field: 'service.name', + }, + { + label: i18n.ADDRESS, + getValues: (serviceData: ObservedEntityData) => + serviceData.details.service?.address, + field: 'service.address', + }, + { + label: i18n.ENVIRONMENT, + getValues: (serviceData: ObservedEntityData) => + serviceData.details.service?.environment, + field: 'service.environment', + }, + { + label: i18n.EPHEMERAL_ID, + getValues: (serviceData: ObservedEntityData) => + serviceData.details.service?.ephemeral_id, + field: 'service.ephemeral_id', + }, + { + label: i18n.NODE_NAME, + getValues: (serviceData: ObservedEntityData) => + serviceData.details.service?.node?.name, + field: 'service.node.name', + }, + { + label: i18n.NODE_ROLES, + getValues: (serviceData: ObservedEntityData) => + serviceData.details.service?.node?.roles, + field: 'service.node.roles', + }, + { + label: i18n.NODE_ROLE, + getValues: (serviceData: ObservedEntityData) => + serviceData.details.service?.node?.role, + field: 'service.node.role', + }, + { + label: i18n.STATE, + getValues: (serviceData: ObservedEntityData) => serviceData.details.service?.state, + field: 'service.state', + }, + { + label: i18n.TYPE, + getValues: (serviceData: ObservedEntityData) => serviceData.details.service?.type, + field: 'service.type', + }, + { + label: i18n.VERSION, + getValues: (serviceData: ObservedEntityData) => + serviceData.details.service?.version, + field: 'service.version', + }, + { + label: i18n.FIRST_SEEN, + render: (serviceData: ObservedEntityData) => + serviceData.firstSeen.date ? ( + + ) : ( + getEmptyTagValue() + ), + }, + { + label: i18n.LAST_SEEN, + render: (serviceData: ObservedEntityData) => + serviceData.lastSeen.date ? ( + + ) : ( + getEmptyTagValue() + ), + }, +]; + +export const useObservedServiceItems = ( + serviceData: ObservedEntityData +): EntityTableRows> => { + if (!serviceData.details) { + return []; + } + + return basicServiceFields; +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/index.test.tsx new file mode 100644 index 0000000000000..96017d03ff5c0 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/index.test.tsx @@ -0,0 +1,97 @@ +/* + * 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 { TestProviders } from '../../../common/mock'; +import type { ServicePanelProps } from '.'; +import { ServicePanel } from '.'; +import type { + FlyoutPanelProps, + ExpandableFlyoutState, + ExpandableFlyoutApi, +} from '@kbn/expandable-flyout'; +import { + useExpandableFlyoutApi, + useExpandableFlyoutState, + useExpandableFlyoutHistory, +} from '@kbn/expandable-flyout'; +import { mockObservedService } from './mocks'; +import { mockServiceRiskScoreState } from '../mocks'; + +const mockProps: ServicePanelProps = { + serviceName: 'test', + contextID: 'test-service-panel', + scopeId: 'test-scope-id', + isDraggable: false, +}; + +jest.mock('../../../common/components/visualization_actions/visualization_embeddable'); + +const mockedUseRiskScore = jest.fn().mockReturnValue(mockServiceRiskScoreState); +jest.mock('../../../entity_analytics/api/hooks/use_risk_score', () => ({ + useRiskScore: () => mockedUseRiskScore(), +})); + +const mockedUseObservedService = jest.fn().mockReturnValue(mockObservedService); + +jest.mock('./hooks/use_observed_service', () => ({ + useObservedService: () => mockedUseObservedService(), +})); + +const mockedUseIsExperimentalFeatureEnabled = jest.fn().mockReturnValue(true); +jest.mock('../../../common/hooks/use_experimental_features', () => ({ + useIsExperimentalFeatureEnabled: () => mockedUseIsExperimentalFeatureEnabled(), +})); + +const flyoutContextValue = { + closeLeftPanel: jest.fn(), +} as unknown as ExpandableFlyoutApi; + +const flyoutHistory = [{ id: 'id1', params: {} }] as unknown as FlyoutPanelProps[]; +jest.mock('@kbn/expandable-flyout', () => ({ + useExpandableFlyoutApi: jest.fn(), + useExpandableFlyoutHistory: jest.fn(), + useExpandableFlyoutState: jest.fn(), +})); + +describe('ServicePanel', () => { + beforeEach(() => { + mockedUseRiskScore.mockReturnValue(mockServiceRiskScoreState); + mockedUseObservedService.mockReturnValue(mockObservedService); + jest.mocked(useExpandableFlyoutHistory).mockReturnValue(flyoutHistory); + jest.mocked(useExpandableFlyoutState).mockReturnValue({} as unknown as ExpandableFlyoutState); + jest.mocked(useExpandableFlyoutApi).mockReturnValue(flyoutContextValue); + }); + + it('renders', () => { + const { getByTestId, queryByTestId } = render( + + + + ); + + expect(getByTestId('service-panel-header')).toBeInTheDocument(); + expect(queryByTestId('securitySolutionFlyoutLoading')).not.toBeInTheDocument(); + expect(getByTestId('securitySolutionFlyoutNavigationExpandDetailButton')).toBeInTheDocument(); + }); + + it('renders loading state when observed service is loading', () => { + mockedUseObservedService.mockReturnValue({ + ...mockObservedService, + isLoading: true, + }); + + const { getByTestId } = render( + + + + ); + + expect(getByTestId('securitySolutionFlyoutLoading')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/index.tsx new file mode 100644 index 0000000000000..1f55f19b896a7 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/index.tsx @@ -0,0 +1,137 @@ +/* + * 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, { useCallback, useMemo } from 'react'; +import type { FlyoutPanelProps } from '@kbn/expandable-flyout'; +import { TableId } from '@kbn/securitysolution-data-table'; +import { noop } from 'lodash/fp'; +import { buildEntityNameFilter } from '../../../../common/search_strategy'; +import { useRefetchQueryById } from '../../../entity_analytics/api/hooks/use_refetch_query_by_id'; +import type { Refetch } from '../../../common/types'; +import { RISK_INPUTS_TAB_QUERY_ID } from '../../../entity_analytics/components/entity_details_flyout/tabs/risk_inputs/risk_inputs_tab'; +import { useCalculateEntityRiskScore } from '../../../entity_analytics/api/hooks/use_calculate_entity_risk_score'; +import { useRiskScore } from '../../../entity_analytics/api/hooks/use_risk_score'; +import { useQueryInspector } from '../../../common/components/page/manage_query'; +import { useGlobalTime } from '../../../common/containers/use_global_time'; +import { FlyoutLoading } from '../../shared/components/flyout_loading'; +import { FlyoutNavigation } from '../../shared/components/flyout_navigation'; +import { ServicePanelContent } from './content'; +import { ServicePanelHeader } from './header'; +import { useObservedService } from './hooks/use_observed_service'; +import { EntityType } from '../../../../common/entity_analytics/types'; +import { EntityDetailsLeftPanelTab } from '../shared/components/left_panel/left_panel_header'; +import { useNavigateToServiceDetails } from './hooks/use_navigate_to_service_details'; + +export interface ServicePanelProps extends Record { + contextID: string; + scopeId: string; + serviceName: string; + isDraggable?: boolean; +} + +export interface ServicePanelExpandableFlyoutProps extends FlyoutPanelProps { + key: 'service-panel'; + params: ServicePanelProps; +} + +export const SERVICE_PANEL_RISK_SCORE_QUERY_ID = 'servicePanelRiskScoreQuery'; +const FIRST_RECORD_PAGINATION = { + cursorStart: 0, + querySize: 1, +}; + +export const ServicePanel = ({ + contextID, + scopeId, + serviceName, + isDraggable, +}: ServicePanelProps) => { + const serviceNameFilterQuery = useMemo( + () => (serviceName ? buildEntityNameFilter(EntityType.service, [serviceName]) : undefined), + [serviceName] + ); + + const riskScoreState = useRiskScore({ + riskEntity: EntityType.service, + filterQuery: serviceNameFilterQuery, + onlyLatest: false, + pagination: FIRST_RECORD_PAGINATION, + }); + + const { inspect, refetch, loading } = riskScoreState; + const { setQuery, deleteQuery } = useGlobalTime(); + const observedService = useObservedService(serviceName, scopeId); + const { data: serviceRisk } = riskScoreState; + const serviceRiskData = serviceRisk && serviceRisk.length > 0 ? serviceRisk[0] : undefined; + const isRiskScoreExist = !!serviceRiskData?.service.risk; + + const refetchRiskInputsTab = useRefetchQueryById(RISK_INPUTS_TAB_QUERY_ID) ?? noop; + const refetchRiskScore = useCallback(() => { + refetch(); + (refetchRiskInputsTab as Refetch)(); + }, [refetch, refetchRiskInputsTab]); + + const { isLoading: recalculatingScore, calculateEntityRiskScore } = useCalculateEntityRiskScore( + EntityType.service, + serviceName, + { onSuccess: refetchRiskScore } + ); + + useQueryInspector({ + deleteQuery, + inspect, + loading, + queryId: SERVICE_PANEL_RISK_SCORE_QUERY_ID, + refetch, + setQuery, + }); + + const { openDetailsPanel, isLinkEnabled } = useNavigateToServiceDetails({ + serviceName, + scopeId, + contextID, + isDraggable, + isRiskScoreExist, + }); + + const openPanelFirstTab = useCallback( + () => + openDetailsPanel({ + tab: EntityDetailsLeftPanelTab.RISK_INPUTS, + }), + [openDetailsPanel] + ); + + if (observedService.isLoading) { + return ; + } + + return ( + <> + + + + + ); +}; + +ServicePanel.displayName = 'ServicePanel'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/mocks/index.ts b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/mocks/index.ts new file mode 100644 index 0000000000000..38e35e7b9f5e2 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/service_right/mocks/index.ts @@ -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 type { ServiceItem } from '../../../../../common/search_strategy'; +import type { ObservedEntityData } from '../../shared/components/observed_entity/types'; + +const observedServiceDetails: ServiceItem = { + service: { + id: ['test id'], + name: ['test name', 'another test name'], + address: ['test address'], + environment: ['test environment'], + ephemeral_id: ['test ephemeral_id'], + node: { + name: ['test node name'], + roles: ['test node roles'], + role: ['test node role'], + }, + roles: ['test roles'], + state: ['test state'], + type: ['test type'], + version: ['test version'], + }, +}; + +export const mockObservedService: ObservedEntityData = { + details: observedServiceDetails, + isLoading: false, + firstSeen: { + isLoading: false, + date: '2023-02-23T20:03:17.489Z', + }, + lastSeen: { + isLoading: false, + date: '2023-02-23T20:03:17.489Z', + }, +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/shared/components/observed_entity/types.ts b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/shared/components/observed_entity/types.ts index f9d9db179d3f6..1ff4a77d2f4e8 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/shared/components/observed_entity/types.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/shared/components/observed_entity/types.ts @@ -22,6 +22,6 @@ export interface EntityAnomalies { export interface ObservedEntityData extends BasicEntityData { firstSeen: FirstLastSeenData; lastSeen: FirstLastSeenData; - anomalies: EntityAnomalies; + anomalies?: EntityAnomalies; details: T; } diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/shared/constants.ts b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/shared/constants.ts index 7dc7a8b321785..ae123243aa04e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/shared/constants.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/shared/constants.ts @@ -7,6 +7,7 @@ import { EntityType } from '../../../../common/entity_analytics/types'; import type { HostPanelExpandableFlyoutProps } from '../host_right'; +import type { ServicePanelExpandableFlyoutProps } from '../service_right'; import type { UserPanelExpandableFlyoutProps } from '../user_right'; export const ONE_WEEK_IN_HOURS = 24 * 7; @@ -25,11 +26,12 @@ export const MANAGED_USER_QUERY_ID = 'managedUserDetailsQuery'; export const HostPanelKey: HostPanelExpandableFlyoutProps['key'] = 'host-panel'; export const UserPanelKey: UserPanelExpandableFlyoutProps['key'] = 'user-panel'; +export const ServicePanelKey: ServicePanelExpandableFlyoutProps['key'] = 'service-panel'; export const EntityPanelKeyByType: Record = { [EntityType.host]: HostPanelKey, [EntityType.user]: UserPanelKey, - [EntityType.service]: undefined, // TODO create service flyout + [EntityType.service]: ServicePanelKey, [EntityType.universal]: undefined, // TODO create universal flyout? }; @@ -37,6 +39,6 @@ export const EntityPanelKeyByType: Record = { export const EntityPanelParamByType: Record = { [EntityType.host]: 'hostName', [EntityType.user]: 'userName', - [EntityType.service]: undefined, // TODO create service flyout + [EntityType.service]: 'serviceName', [EntityType.universal]: undefined, // TODO create universal flyout? }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/user_details_left/tabs.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/user_details_left/tabs.tsx index 02e2dedcfeb7a..972eafb5f0f7b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/user_details_left/tabs.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/user_details_left/tabs.tsx @@ -21,7 +21,7 @@ import type { import { ENTRA_TAB_TEST_ID, OKTA_TAB_TEST_ID } from './test_ids'; import { AssetDocumentTab } from './tabs/asset_document'; import { DocumentDetailsProvider } from '../../document_details/shared/context'; -import { EntityType } from '../../../../common/entity_analytics/types'; +import { EntityIdentifierFields, EntityType } from '../../../../common/entity_analytics/types'; import type { LeftPanelTabsType } from '../shared/components/left_panel/left_panel_header'; import { EntityDetailsLeftPanelTab } from '../shared/components/left_panel/left_panel_header'; @@ -57,7 +57,7 @@ export const useTabs = ( } if (hasMisconfigurationFindings || hasNonClosedAlerts) { - tabs.push(getInsightsInputTab({ name, fieldName: 'user.name' })); + tabs.push(getInsightsInputTab({ name, fieldName: EntityIdentifierFields.userName })); } return tabs; diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/user_right/content.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/user_right/content.tsx index 9688c6f3b5143..ea81f5eb4dcfd 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/user_right/content.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/user_right/content.tsx @@ -17,7 +17,7 @@ import { FlyoutRiskSummary } from '../../../entity_analytics/components/risk_sum import type { RiskScoreState } from '../../../entity_analytics/api/hooks/use_risk_score'; import { ManagedUser } from './components/managed_user'; import type { ManagedUserData } from './types'; -import { EntityType } from '../../../../common/entity_analytics/types'; +import { EntityIdentifierFields, EntityType } from '../../../../common/entity_analytics/types'; import { USER_PANEL_RISK_SCORE_QUERY_ID } from '.'; import { FlyoutBody } from '../../shared/components/flyout_body'; import { ObservedEntity } from '../shared/components/observed_entity'; @@ -75,12 +75,12 @@ export const UserPanelContent = ({ )} { contextID: string; @@ -99,7 +99,7 @@ export const UserPanel = ({ const { hasMisconfigurationFindings } = useHasMisconfigurations('user.name', userName); const { hasNonClosedAlerts } = useNonClosedAlerts({ - field: 'user.name', + field: EntityIdentifierFields.userName, value: userName, to, from, @@ -121,7 +121,7 @@ export const UserPanel = ({ scopeId, contextID, isDraggable, - isRiskScoreExist: !!userRiskData?.user?.risk, + isRiskScoreExist, hasMisconfigurationFindings, hasNonClosedAlerts, isPreviewMode, diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/index.tsx index 2508b0cb6cc09..6ec67155e01a5 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/index.tsx @@ -46,7 +46,11 @@ import { HostDetailsPanel, HostDetailsPanelKey } from './entity_details/host_det import { NetworkPanel, NetworkPanelKey, NetworkPreviewPanelKey } from './network_details'; import type { AnalyzerPanelExpandableFlyoutProps } from './document_details/analyzer_panels'; import { AnalyzerPanel } from './document_details/analyzer_panels'; -import { UserPanelKey, HostPanelKey } from './entity_details/shared/constants'; +import { UserPanelKey, HostPanelKey, ServicePanelKey } from './entity_details/shared/constants'; +import type { ServicePanelExpandableFlyoutProps } from './entity_details/service_right'; +import { ServicePanel } from './entity_details/service_right'; +import type { ServiceDetailsExpandableFlyoutProps } from './entity_details/service_details_left'; +import { ServiceDetailsPanel, ServiceDetailsPanelKey } from './entity_details/service_details_left'; /** * List of all panels that will be used within the document details expandable flyout. @@ -159,6 +163,17 @@ const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels'] ), }, + + { + key: ServicePanelKey, + component: (props) => , + }, + { + key: ServiceDetailsPanelKey, + component: (props) => ( + + ), + }, ]; export const SECURITY_SOLUTION_ON_CLOSE_EVENT = `expandable-flyout-on-close-${Flyouts.securitySolution}`; diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/shared/hooks/use_on_expandable_flyout_close.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/shared/hooks/use_on_expandable_flyout_close.test.tsx index 2a4e5576e24bc..72039ea06a60b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/shared/hooks/use_on_expandable_flyout_close.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/shared/hooks/use_on_expandable_flyout_close.test.tsx @@ -21,7 +21,7 @@ describe('useOnExpandableFlyoutClose', () => { window.removeEventListener = jest.fn().mockImplementationOnce((event, callback) => {}); - renderHook(() => useOnExpandableFlyoutClose({ callback: callbackFct })); + const { unmount } = renderHook(() => useOnExpandableFlyoutClose({ callback: callbackFct })); window.dispatchEvent( new CustomEvent(TIMELINE_ON_CLOSE_EVENT, { @@ -30,6 +30,9 @@ describe('useOnExpandableFlyoutClose', () => { ); expect(callbackFct).toHaveBeenCalledWith(Flyouts.timeline); + + unmount(); + expect(window.removeEventListener).toBeCalled(); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/helper_hooks.tsx b/x-pack/solutions/security/plugins/security_solution/public/helper_hooks.tsx index 90d15643aec8b..c22513a989a06 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/helper_hooks.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/helper_hooks.tsx @@ -27,5 +27,5 @@ export const useOnOpenCloseHandler = (): [boolean, () => void, () => void] => { */ export const useHasSecurityCapability = (capability: string): boolean => { const { capabilities } = useKibana().services.application; - return !!capabilities.siem[capability]; + return !!capabilities.siemV2[capability]; }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/helpers.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/helpers.test.tsx index 04eaad34f14ce..ab21a78c8deff 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/helpers.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/helpers.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import type { Capabilities } from '@kbn/core/public'; -import { CASES_FEATURE_ID, SERVER_APP_ID } from '../common/constants'; +import { CASES_FEATURE_ID, SECURITY_FEATURE_ID } from '../common/constants'; import { mockEcsDataWithAlert } from './common/mock'; import { ALERT_RULE_UUID, ALERT_RULE_NAME, ALERT_RULE_PARAMETERS } from '@kbn/rule-data-utils'; import { @@ -87,7 +87,7 @@ describe('#getSubPluginRoutesByCapabilities', () => { const routes = getSubPluginRoutesByCapabilities( mockSubPlugins, set(mockServices, 'application.capabilities', { - [SERVER_APP_ID]: { show: true, crud: false }, + [SECURITY_FEATURE_ID]: { show: true, crud: false }, [CASES_FEATURE_ID]: noCasesCapabilities(), }) ); @@ -107,7 +107,7 @@ describe('#getSubPluginRoutesByCapabilities', () => { const routes = getSubPluginRoutesByCapabilities( mockSubPlugins, set(mockServices, 'application.capabilities', { - [SERVER_APP_ID]: { show: false, crud: false }, + [SECURITY_FEATURE_ID]: { show: false, crud: false }, [CASES_FEATURE_ID]: readCasesCapabilities(), }) ); @@ -126,7 +126,7 @@ describe('#getSubPluginRoutesByCapabilities', () => { const routes = getSubPluginRoutesByCapabilities( mockSubPlugins, set(mockServices, 'application.capabilities', { - [SERVER_APP_ID]: { show: false, crud: false }, + [SECURITY_FEATURE_ID]: { show: false, crud: false }, [CASES_FEATURE_ID]: noCasesCapabilities(), }) ); @@ -157,7 +157,7 @@ describe('#isSubPluginAvailable', () => { it('plugin outsides of cases should be available if siem privilege is all and independently of cases privileges', () => { expect( isSubPluginAvailable('pluginKey', { - [SERVER_APP_ID]: { show: true, crud: true }, + [SECURITY_FEATURE_ID]: { show: true, crud: true }, [CASES_FEATURE_ID]: noCasesCapabilities(), } as unknown as Capabilities) ).toBeTruthy(); @@ -166,7 +166,7 @@ describe('#isSubPluginAvailable', () => { it('plugin outsides of cases should be available if siem privilege is read and independently of cases privileges', () => { expect( isSubPluginAvailable('pluginKey', { - [SERVER_APP_ID]: { show: true, crud: false }, + [SECURITY_FEATURE_ID]: { show: true, crud: false }, [CASES_FEATURE_ID]: noCasesCapabilities(), } as unknown as Capabilities) ).toBeTruthy(); @@ -175,7 +175,7 @@ describe('#isSubPluginAvailable', () => { it('plugin outsides of cases should NOT be available if siem privilege is none and independently of cases privileges', () => { expect( isSubPluginAvailable('pluginKey', { - [SERVER_APP_ID]: { show: false, crud: false }, + [SECURITY_FEATURE_ID]: { show: false, crud: false }, [CASES_FEATURE_ID]: noCasesCapabilities(), } as unknown as Capabilities) ).toBeFalsy(); @@ -184,7 +184,7 @@ describe('#isSubPluginAvailable', () => { it('cases plugin should be available if cases privilege is all and independently of siem privileges', () => { expect( isSubPluginAvailable('cases', { - [SERVER_APP_ID]: { show: false, crud: false }, + [SECURITY_FEATURE_ID]: { show: false, crud: false }, [CASES_FEATURE_ID]: allCasesCapabilities(), } as unknown as Capabilities) ).toBeTruthy(); @@ -193,7 +193,7 @@ describe('#isSubPluginAvailable', () => { it('cases plugin should be available if cases privilege is read and independently of siem privileges', () => { expect( isSubPluginAvailable('cases', { - [SERVER_APP_ID]: { show: false, crud: false }, + [SECURITY_FEATURE_ID]: { show: false, crud: false }, [CASES_FEATURE_ID]: readCasesCapabilities(), } as unknown as Capabilities) ).toBeTruthy(); @@ -202,7 +202,7 @@ describe('#isSubPluginAvailable', () => { it('cases plugin should NOT be available if cases privilege is none independently of siem privileges', () => { expect( isSubPluginAvailable('pluginKey', { - [SERVER_APP_ID]: { show: false, crud: false }, + [SECURITY_FEATURE_ID]: { show: false, crud: false }, [CASES_FEATURE_ID]: noCasesCapabilities(), } as unknown as Capabilities) ).toBeFalsy(); diff --git a/x-pack/solutions/security/plugins/security_solution/public/helpers.tsx b/x-pack/solutions/security/plugins/security_solution/public/helpers.tsx index ffe7b2dd9668d..5390f8e45f868 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/helpers.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/helpers.tsx @@ -24,7 +24,6 @@ import { DASHBOARDS_PATH, EXCEPTIONS_PATH, RULES_PATH, - SERVER_APP_ID, THREAT_INTELLIGENCE_PATH, } from '../common/constants'; import type { @@ -39,6 +38,7 @@ import { CASES_SUB_PLUGIN_KEY } from './types'; import { timelineActions } from './timelines/store'; import { TimelineId } from '../common/types'; import { SourcererScopeName } from './sourcerer/store/model'; +import { hasAccessToSecuritySolution } from './helpers_access'; export const parseRoute = (location: Pick) => { if (!isEmpty(location.hash)) { @@ -234,7 +234,7 @@ export const isSubPluginAvailable = (pluginKey: string, capabilities: Capabiliti if (CASES_SUB_PLUGIN_KEY === pluginKey) { return capabilities[CASES_FEATURE_ID].read_cases === true; } - return capabilities[SERVER_APP_ID].show === true; + return hasAccessToSecuritySolution(capabilities); }; const siemSignalsFieldMappings: Record = { diff --git a/x-pack/solutions/security/plugins/security_solution/public/helpers_access.test.ts b/x-pack/solutions/security/plugins/security_solution/public/helpers_access.test.ts new file mode 100644 index 0000000000000..245d8d0686eb8 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/helpers_access.test.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { Capabilities } from '@kbn/core/public'; +import { SECURITY_FEATURE_ID } from '../common/constants'; +import { hasAccessToSecuritySolution } from './helpers_access'; + +const baseCapabilities: Capabilities = { + navLinks: {}, + management: {}, + catalogue: {}, +}; + +describe('access helpers', () => { + describe('hasAccessToSecuritySolution', () => { + it('should return true for users with correct capabilities', () => { + expect( + hasAccessToSecuritySolution({ + ...baseCapabilities, + [SECURITY_FEATURE_ID]: { show: true }, + }) + ).toBe(true); + }); + + it('should return false for users with incorrect capabilities', () => { + expect( + hasAccessToSecuritySolution({ + ...baseCapabilities, + [SECURITY_FEATURE_ID]: { show: false }, + }) + ).toBe(false); + + expect( + hasAccessToSecuritySolution({ + ...baseCapabilities, + [SECURITY_FEATURE_ID]: {}, + }) + ).toBe(false); + + expect(hasAccessToSecuritySolution(baseCapabilities)).toBe(false); + }); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/helpers_access.ts b/x-pack/solutions/security/plugins/security_solution/public/helpers_access.ts new file mode 100644 index 0000000000000..bcf54354a459b --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/helpers_access.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 type { Capabilities } from '@kbn/core/public'; +import { SECURITY_FEATURE_ID } from '../common/constants'; + +export function hasAccessToSecuritySolution(capabilities: Capabilities) { + return ( + // Using `siemV2` + capabilities[SECURITY_FEATURE_ID]?.show === true + ); +} diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/artifacts/artifact_tabs_in_policy_details.cy.ts b/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/artifacts/artifact_tabs_in_policy_details.cy.ts index 4aa8085fbf571..b6232dc052e3b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/artifacts/artifact_tabs_in_policy_details.cy.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/artifacts/artifact_tabs_in_policy_details.cy.ts @@ -45,7 +45,7 @@ const getRoleWithoutArtifactPrivilege = (privilegePrefix: string) => { ...endpointSecurityPolicyManagerRole.kibana[0], feature: { ...endpointSecurityPolicyManagerRole.kibana[0].feature, - siem: endpointSecurityPolicyManagerRole.kibana[0].feature.siem.filter( + siemV2: endpointSecurityPolicyManagerRole.kibana[0].feature.siemV2.filter( (privilege) => privilege !== `${privilegePrefix}all` ), }, diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/endpoint_list/endpoints_rbac_mocked_data.cy.ts b/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/endpoint_list/endpoints_rbac_mocked_data.cy.ts index 62786effd8303..42874e420138c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/endpoint_list/endpoints_rbac_mocked_data.cy.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/endpoint_list/endpoints_rbac_mocked_data.cy.ts @@ -36,8 +36,8 @@ describe('Endpoints RBAC', { tags: ['@ess'] }, () => { ...base.kibana[0], feature: { ...base.kibana[0].feature, - siem: [ - ...base.kibana[0].feature.siem, + siemV2: [ + ...base.kibana[0].feature.siemV2, `endpoint_list_all`, `policy_management_${endpointPolicyManagementPrivilege}`, ], diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/rbac/endpoint_role_rbac.cy.ts b/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/rbac/endpoint_role_rbac.cy.ts index b97b37191a951..715cde443e6e3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/rbac/endpoint_role_rbac.cy.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/rbac/endpoint_role_rbac.cy.ts @@ -31,7 +31,7 @@ describe.skip( () => { const getAllSubFeatureRows = (): Cypress.Chainable> => { return cy - .get('#featurePrivilegeControls_siem') + .get('#featurePrivilegeControls_siemV2') .findByTestSubj('mutexSubFeaturePrivilegeControl') .closest('.euiFlexGroup'); }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/rbac/endpoint_role_rbac_with_space_awareness.cy.ts b/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/rbac/endpoint_role_rbac_with_space_awareness.cy.ts index 41f6613be88be..93fbc7ef76f27 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/rbac/endpoint_role_rbac_with_space_awareness.cy.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/rbac/endpoint_role_rbac_with_space_awareness.cy.ts @@ -88,7 +88,7 @@ describe( .findByTestSubj(`space-avatar-${spaceId}`) .should('exist'); - cy.get('#row_siem_expansion') + cy.get('#row_siemV2_expansion') .findByTestSubj('subFeatureEntry') .then(($element) => { const features: string[] = []; @@ -119,7 +119,7 @@ describe( it('should not display the privilege tooltip', () => { ENDPOINT_SUB_FEATURE_PRIVILEGE_IDS.forEach((subFeaturePrivilegeId) => { - cy.getByTestSubj(`securitySolution_siem_${subFeaturePrivilegeId}_nameTooltip`).should( + cy.getByTestSubj(`securitySolution_siemV2_${subFeaturePrivilegeId}_nameTooltip`).should( 'not.exist' ); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/cypress/fixtures/role_with_artifact_read_privilege.ts b/x-pack/solutions/security/plugins/security_solution/public/management/cypress/fixtures/role_with_artifact_read_privilege.ts index 247b491f04632..25bc5d2da1f8b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/cypress/fixtures/role_with_artifact_read_privilege.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/management/cypress/fixtures/role_with_artifact_read_privilege.ts @@ -17,8 +17,8 @@ export const getRoleWithArtifactReadPrivilege = (privilegePrefix: string) => { ...endpointSecurityPolicyManagerRole.kibana[0], feature: { ...endpointSecurityPolicyManagerRole.kibana[0].feature, - siem: [ - ...endpointSecurityPolicyManagerRole.kibana[0].feature.siem.filter( + siemV2: [ + ...endpointSecurityPolicyManagerRole.kibana[0].feature.siemV2.filter( (privilege) => privilege !== `${privilegePrefix}all` ), `${privilegePrefix}read`, diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/cypress/screens/stack_management/role_page.ts b/x-pack/solutions/security/plugins/security_solution/public/management/cypress/screens/stack_management/role_page.ts index a3e7bbc7e4e89..1b6d7e6c92548 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/cypress/screens/stack_management/role_page.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/management/cypress/screens/stack_management/role_page.ts @@ -65,11 +65,13 @@ export const getSecuritySolutionCategoryKibanaPrivileges = (): Cypress.Chainable * kibana feature privileges grouping. This is the area where Endpoint related RBAC is managed */ export const expandEndpointSecurityFeaturePrivileges = (): Cypress.Chainable => { - return cy.getByTestSubj('featurePrivilegeControls_securitySolution_siem_accordionToggle').click(); + return cy + .getByTestSubj('featurePrivilegeControls_securitySolution_siemV2_accordionToggle') + .click(); }; export const getEndpointSecurityFeaturePrivileges = () => { - return cy.getByTestSubj('featureCategory_securitySolution_siem'); + return cy.getByTestSubj('featureCategory_securitySolution_siemV2'); }; /** @@ -101,7 +103,9 @@ export const setKibanaPrivilegeSpace = (spaceId: string) => { export const setSecuritySolutionEndpointGroupPrivilege = ( privilege: 'all' | 'read' | 'none' ): Cypress.Chainable> => { - return getSecuritySolutionCategoryKibanaPrivileges().findByTestSubj(`siem_${privilege}`).click(); + return getSecuritySolutionCategoryKibanaPrivileges() + .findByTestSubj(`siemV2_${privilege}`) + .click(); }; /** @@ -144,7 +148,7 @@ export const setEndpointSubFeaturePrivilege = ( privilege: 'all' | 'read' | 'none' ): Cypress.Chainable> => { return getEndpointSecurityFeaturePrivileges() - .findByTestSubj(`securitySolution_siem_${feature}_privilegeGroup`) + .findByTestSubj(`securitySolution_siemV2_${feature}_privilegeGroup`) .find(`button[title="${privilegeMapToTitle[privilege]}"]`) .click(); }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/links.ts b/x-pack/solutions/security/plugins/security_solution/public/management/links.ts index 909395df8df4f..fc9f8967859ca 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/management/links.ts @@ -24,7 +24,7 @@ import { POLICIES_PATH, RESPONSE_ACTIONS_HISTORY_PATH, SecurityPageName, - SERVER_APP_ID, + SECURITY_FEATURE_ID, TRUSTED_APPS_PATH, } from '../../common/constants'; import { @@ -100,7 +100,7 @@ export const links: LinkItem = { skipUrlState: true, hideTimeline: true, globalNavPosition: 11, - capabilities: [`${SERVER_APP_ID}.show`], + capabilities: [`${SECURITY_FEATURE_ID}.show`], globalSearchKeywords: [ i18n.translate('xpack.securitySolution.appLinks.manage', { defaultMessage: 'Manage', @@ -189,7 +189,7 @@ export const links: LinkItem = { path: ENTITY_ANALYTICS_MANAGEMENT_PATH, skipUrlState: true, hideTimeline: true, - capabilities: [`${SERVER_APP_ID}.entity-analytics`], + capabilities: [`${SECURITY_FEATURE_ID}.entity-analytics`], experimentalKey: 'riskScoringRoutesEnabled', licenseType: 'platinum', }, @@ -203,7 +203,7 @@ export const links: LinkItem = { path: ENTITY_ANALYTICS_ENTITY_STORE_MANAGEMENT_PATH, skipUrlState: true, hideTimeline: true, - capabilities: [`${SERVER_APP_ID}.entity-analytics`], + capabilities: [`${SECURITY_FEATURE_ID}.entity-analytics`], }, { id: SecurityPageName.responseActionsHistory, diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_results.tsx b/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_results.tsx index 887792b0b17fd..764b482a66826 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_results.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_results.tsx @@ -122,13 +122,15 @@ export const WorkflowInsightsResults = ({ - {insight.value} + {insight.metadata.display_name || insight.value} {insight.message} - {item.entries[0].type === 'match' && item.entries[0].value} + {item.entries[0].type === 'match' && + item.entries[0].field === 'process.executable.caseless' && + item.entries[0].value} diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/mocks.tsx b/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/mocks.tsx index 945a841c132fd..3a480b47c9d08 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/mocks.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/mocks.tsx @@ -96,7 +96,7 @@ export const createFleetContextRendererMock = (): AppContextTestRender => { startServices.application.capabilities = deepFreeze({ ...startServices.application.capabilities, - siem: { show: true, crud: true }, + siemV2: { show: true, crud: true }, }); return ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_list.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_list.test.tsx index c3f6185701f13..80e3998e191c7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_list.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_list.test.tsx @@ -61,9 +61,10 @@ describe('When on the trusted applications page', () => { it('should search using expected exception item fields', async () => { const expectedFilterString = parseQueryFilterToKQL('fooFooFoo', SEARCHABLE_FIELDS); - const { findAllByTestId } = render(); + const { getAllByTestId } = render(); + await waitFor(async () => { - await expect(findAllByTestId('trustedAppsListPage-card')).resolves.toHaveLength(10); + expect(getAllByTestId('trustedAppsListPage-card')).toHaveLength(10); }); apiMocks.responseProvider.exceptionsFind.mockClear(); diff --git a/x-pack/solutions/security/plugins/security_solution/public/notes/components/notes_list.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/notes/components/notes_list.test.tsx index d32b508d03037..56ca7a8e833a5 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/notes/components/notes_list.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/notes/components/notes_list.test.tsx @@ -44,7 +44,8 @@ describe('NotesList', () => { (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(false); useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true, read: true }, + timelinePrivileges: { read: true }, + notesPrivileges: { crud: true, read: true }, }); }); @@ -103,7 +104,8 @@ describe('NotesList', () => { it('should not render a delete icon when the user does not have crud privileges', () => { useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: false, read: true }, + timelinePrivileges: { read: true }, + notesPrivileges: { crud: false, read: true }, }); const { queryByTestId } = render( diff --git a/x-pack/solutions/security/plugins/security_solution/public/notes/components/notes_list.tsx b/x-pack/solutions/security/plugins/security_solution/public/notes/components/notes_list.tsx index 344935413731e..56b3579797aef 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/notes/components/notes_list.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/notes/components/notes_list.tsx @@ -59,8 +59,8 @@ export interface NotesListProps { * 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(({ notes, options }: NotesListProps) => { - const { kibanaSecuritySolutionsPrivileges } = useUserPrivileges(); - const canDeleteNotes = kibanaSecuritySolutionsPrivileges.crud; + const { notesPrivileges } = useUserPrivileges(); + const canDeleteNotes = notesPrivileges.crud; const createStatus = useSelector((state: State) => selectCreateNoteStatus(state)); diff --git a/x-pack/solutions/security/plugins/security_solution/public/notes/components/open_timeline_button.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/notes/components/open_timeline_button.test.tsx index c6a2629494758..108ee6f6886a9 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/notes/components/open_timeline_button.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/notes/components/open_timeline_button.test.tsx @@ -11,9 +11,11 @@ import { OpenTimelineButtonIcon } from './open_timeline_button'; import type { Note } from '../../../common/api/timeline'; import { OPEN_TIMELINE_BUTTON_TEST_ID } from './test_ids'; import { useQueryTimelineById } from '../../timelines/components/open_timeline/helpers'; +import { useUserPrivileges } from '../../common/components/user_privileges'; jest.mock('../../common/hooks/use_experimental_features'); jest.mock('../../timelines/components/open_timeline/helpers'); +jest.mock('../../common/components/user_privileges'); const note: Note = { eventId: '1', @@ -29,12 +31,25 @@ const note: Note = { const index = 0; describe('OpenTimelineButtonIcon', () => { + beforeEach(() => { + (useUserPrivileges as jest.Mock).mockReturnValue({ timelinePrivileges: { read: true } }); + }); + it('should render the timeline icon', () => { const { getByTestId } = render(); expect(getByTestId(`${OPEN_TIMELINE_BUTTON_TEST_ID}-${index}`)).toBeInTheDocument(); }); + it('should disable the button if the user does not have the correct privileges', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ timelinePrivileges: { read: false } }); + (useQueryTimelineById as jest.Mock).mockReturnValue(jest.fn()); + + const { getByTestId } = render(); + + expect(getByTestId(`${OPEN_TIMELINE_BUTTON_TEST_ID}-${index}`)).toHaveAttribute('disabled'); + }); + it('should call openTimeline with the correct values', () => { const openTimeline = jest.fn(); (useQueryTimelineById as jest.Mock).mockReturnValue(openTimeline); diff --git a/x-pack/solutions/security/plugins/security_solution/public/notes/components/open_timeline_button.tsx b/x-pack/solutions/security/plugins/security_solution/public/notes/components/open_timeline_button.tsx index 91f3a722ebeeb..81a1cf2a05e7f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/notes/components/open_timeline_button.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/notes/components/open_timeline_button.tsx @@ -11,6 +11,7 @@ import { i18n } from '@kbn/i18n'; import { useQueryTimelineById } from '../../timelines/components/open_timeline/helpers'; import { OPEN_TIMELINE_BUTTON_TEST_ID } from './test_ids'; import type { Note } from '../../../common/api/timeline'; +import { useUserPrivileges } from '../../common/components/user_privileges'; const OPEN_TIMELINE = i18n.translate('xpack.securitySolution.notes.management.openTimelineButton', { defaultMessage: 'Open saved timeline', @@ -31,6 +32,10 @@ export interface OpenTimelineButtonIconProps { * Renders a button to open the timeline associated with a note */ export const OpenTimelineButtonIcon = memo(({ note, index }: OpenTimelineButtonIconProps) => { + const { + timelinePrivileges: { read: canReadTimelines }, + } = useUserPrivileges(); + const queryTimelineById = useQueryTimelineById(); const openTimeline = useCallback( ({ timelineId }: { timelineId: string }) => @@ -51,6 +56,7 @@ export const OpenTimelineButtonIcon = memo(({ note, index }: OpenTimelineButtonI color="text" iconType="timelineWithArrow" onClick={() => openTimeline(note)} + disabled={!canReadTimelines} /> ); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/notes/hooks/use_fetch_notes.test.ts b/x-pack/solutions/security/plugins/security_solution/public/notes/hooks/use_fetch_notes.test.ts index b7fa3ab3fc519..f95a262b506a3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/notes/hooks/use_fetch_notes.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/notes/hooks/use_fetch_notes.test.ts @@ -10,6 +10,7 @@ import { useDispatch } from 'react-redux'; import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features'; import { fetchNotesByDocumentIds } from '../store/notes.slice'; import { useFetchNotes } from './use_fetch_notes'; +import { useUserPrivileges } from '../../common/components/user_privileges'; jest.mock('react-redux', () => ({ useDispatch: jest.fn(), @@ -23,6 +24,8 @@ jest.mock('../store/notes.slice', () => ({ fetchNotesByDocumentIds: jest.fn(), })); +jest.mock('../../common/components/user_privileges'); + const mockedUseDispatch = useDispatch as jest.MockedFunction; const mockedUseIsExperimentalFeatureEnabled = useIsExperimentalFeatureEnabled as jest.MockedFunction; @@ -33,6 +36,9 @@ describe('useFetchNotes', () => { beforeEach(() => { mockDispatch = jest.fn(); mockedUseDispatch.mockReturnValue(mockDispatch); + (useUserPrivileges as jest.Mock).mockReturnValue({ + notesPrivileges: { read: true }, + }); }); afterEach(() => { @@ -61,6 +67,19 @@ describe('useFetchNotes', () => { expect(mockDispatch).not.toHaveBeenCalled(); }); + it('should not dispatch action when user has insufficient privileges', () => { + mockedUseIsExperimentalFeatureEnabled.mockReturnValue(false); + (useUserPrivileges as jest.Mock).mockReturnValue({ + notesPrivileges: { read: false }, + }); + const { result } = renderHook(() => useFetchNotes()); + + const events = [{ _id: '1' }, { _id: '2' }, { _id: '3' }]; + result.current.onLoad(events); + + expect(mockDispatch).not.toHaveBeenCalled(); + }); + it('should dispatch fetchNotesByDocumentIds with correct ids when conditions are met', () => { mockedUseIsExperimentalFeatureEnabled.mockReturnValue(false); const { result } = renderHook(() => useFetchNotes()); diff --git a/x-pack/solutions/security/plugins/security_solution/public/notes/hooks/use_fetch_notes.ts b/x-pack/solutions/security/plugins/security_solution/public/notes/hooks/use_fetch_notes.ts index cdfa8b7600dfd..00f3740cb8b44 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/notes/hooks/use_fetch_notes.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/notes/hooks/use_fetch_notes.ts @@ -8,6 +8,7 @@ import { useCallback } from 'react'; import { useDispatch } from 'react-redux'; import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features'; +import { useUserPrivileges } from '../../common/components/user_privileges'; import { fetchNotesByDocumentIds } from '../store/notes.slice'; export interface UseFetchNotesResult { @@ -25,16 +26,19 @@ export const useFetchNotes = (): UseFetchNotesResult => { const securitySolutionNotesDisabled = useIsExperimentalFeatureEnabled( 'securitySolutionNotesDisabled' ); + const { + notesPrivileges: { read: canReadNotes }, + } = useUserPrivileges(); const onLoad = useCallback( (events: Array>) => { - if (securitySolutionNotesDisabled || events.length === 0) return; + if (!canReadNotes || securitySolutionNotesDisabled || events.length === 0) return; const eventIds: string[] = events .map((event) => event._id) .filter((id) => id != null) as string[]; dispatch(fetchNotesByDocumentIds({ documentIds: eventIds })); }, - [dispatch, securitySolutionNotesDisabled] + [dispatch, securitySolutionNotesDisabled, canReadNotes] ); return { onLoad }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/notes/links.ts b/x-pack/solutions/security/plugins/security_solution/public/notes/links.ts index 628904ae30c41..94c1233dae1f1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/notes/links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/notes/links.ts @@ -6,7 +6,12 @@ */ import { i18n } from '@kbn/i18n'; -import { NOTES_PATH, SecurityPageName, SERVER_APP_ID } from '../../common/constants'; +import { + NOTES_PATH, + SECURITY_FEATURE_ID, + SecurityPageName, + NOTES_FEATURE_ID, +} from '../../common/constants'; import { NOTES } from '../app/translations'; import type { LinkItem } from '../common/links/types'; @@ -18,7 +23,8 @@ export const links: LinkItem = { defaultMessage: 'Oversee, revise, and revisit the notes attached to alerts, events and Timelines.', }), - capabilities: [`${SERVER_APP_ID}.show`], + // It only makes sense to show this link when the user is also granted access to security solution + capabilities: [[`${SECURITY_FEATURE_ID}.show`, `${NOTES_FEATURE_ID}.read`]], landingIcon: 'filebeatApp', skipUrlState: true, hideTimeline: true, diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/links.ts b/x-pack/solutions/security/plugins/security_solution/public/onboarding/links.ts index ea9e603a36fac..05519b12b06ff 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/links.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import { ONBOARDING_PATH, SecurityPageName, SERVER_APP_ID } from '../../common/constants'; +import { ONBOARDING_PATH, SecurityPageName, SECURITY_FEATURE_ID } from '../../common/constants'; import { GETTING_STARTED } from '../app/translations'; import type { LinkItem } from '../common/links/types'; @@ -14,7 +14,7 @@ export const onboardingLinks: LinkItem = { id: SecurityPageName.landing, title: GETTING_STARTED, path: ONBOARDING_PATH, - capabilities: [`${SERVER_APP_ID}.show`], + capabilities: [`${SECURITY_FEATURE_ID}.show`], globalSearchKeywords: [ i18n.translate('xpack.securitySolution.appLinks.getStarted', { defaultMessage: 'Getting started', diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.test.tsx index 40a9fab612ad6..d3db4c743b53d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.test.tsx @@ -14,7 +14,9 @@ import { CASES_FEATURE_ID } from '../../../../../common/constants'; import { TestProviders } from '../../../../common/mock/test_providers'; import { useAlertsByStatus } from './use_alerts_by_status'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; +jest.mock('../../../../common/components/user_privileges'); jest.mock('../../../../common/lib/kibana/kibana_react'); jest.mock('../../../../common/hooks/use_experimental_features', () => { return { useIsExperimentalFeatureEnabled: jest.fn() }; @@ -63,6 +65,9 @@ describe('AlertsByStatus', () => { isLoading: true, }); (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(false); + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { read: true }, + }); }); test('render HoverVisibilityContainer', () => { @@ -108,6 +113,20 @@ describe('AlertsByStatus', () => { expect(getByTestId('view-details-button')).toHaveTextContent('Investigate in Timeline'); }); + test('shows correct names when entity filter IS provided AND user does not have timeline privileges', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: {}, + }); + const { getByText, getByTestId } = render( + + + + ); + + expect(getByText('Alerts by Severity')).toBeInTheDocument(); + expect(getByTestId('view-details-button')).toHaveTextContent('View alerts'); + }); + test('render HeaderSection', () => { const { container } = render( diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx index 60dcceb894119..7f2dd03ad8079 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx @@ -51,6 +51,7 @@ import { useQueryToggle } from '../../../../common/containers/query_toggle'; import { VIEW_ALERTS } from '../../../pages/translations'; import { SEVERITY_COLOR } from '../utils'; import { FormattedCount } from '../../../../common/components/formatted_number'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; import { ChartLabel } from './chart_label'; import { Legend } from '../../../../common/components/charts/legend'; import { emptyDonutColor } from '../../../../common/components/charts/donutchart_empty'; @@ -109,6 +110,9 @@ export const AlertsByStatus = ({ const { toggleStatus, setToggleStatus } = useQueryToggle(DETECTION_RESPONSE_ALERTS_BY_STATUS_ID); const { openTimelineWithFilters } = useNavigateToTimeline(); const navigateToAlerts = useNavigateToAlertsPageWithFilters(); + const { + timelinePrivileges: { read: canAccessTimelines }, + } = useUserPrivileges(); const { onClick: goToAlerts, href } = useGetSecuritySolutionLinkProps()({ deepLinkId: SecurityPageName.alerts, }); @@ -125,15 +129,16 @@ export const AlertsByStatus = ({ const detailsButtonOptions = useMemo( () => ({ - name: entityFilter ? INVESTIGATE_IN_TIMELINE : VIEW_ALERTS, - href: entityFilter ? undefined : href, - onClick: entityFilter - ? async () => { - await openTimelineWithFilters([[entityFilter, eventKindSignalFilter]]); - } - : goToAlerts, + name: canAccessTimelines && entityFilter ? INVESTIGATE_IN_TIMELINE : VIEW_ALERTS, + href: canAccessTimelines && entityFilter ? undefined : href, + onClick: + canAccessTimelines && entityFilter + ? async () => { + await openTimelineWithFilters([[entityFilter, eventKindSignalFilter]]); + } + : goToAlerts, }), - [entityFilter, href, goToAlerts, openTimelineWithFilters] + [entityFilter, href, goToAlerts, openTimelineWithFilters, canAccessTimelines] ); const { diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/sidebar/sidebar.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/sidebar/sidebar.test.tsx index 8835fc0e48f27..dfc376e986ec5 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/sidebar/sidebar.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/sidebar/sidebar.test.tsx @@ -6,16 +6,17 @@ */ import React from 'react'; -import { mount } from 'enzyme'; -import { waitFor } from '@testing-library/react'; +import { screen, render, waitFor } from '@testing-library/react'; import { TestProviders } from '../../../common/mock'; import { Sidebar } from './sidebar'; import { useKibana } from '../../../common/lib/kibana'; import type { CaseUiClientMock } from '@kbn/cases-plugin/public/mocks'; import { casesPluginMock } from '@kbn/cases-plugin/public/mocks'; import { noCasesPermissions, readCasesPermissions } from '../../../cases_test_utils'; +import { useUserPrivileges } from '../../../common/components/user_privileges'; jest.mock('../../../common/lib/kibana'); +jest.mock('../../../common/components/user_privileges'); const useKibanaMock = useKibana as jest.MockedFunction; @@ -35,33 +36,64 @@ describe('Sidebar', () => { }, }, } as unknown as ReturnType); + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { read: true }, + }); }); it('does not render the recently created cases section when the user does not have read permissions', async () => { casesMock.helpers.canUseCases.mockReturnValue(noCasesPermissions()); - await waitFor(() => - mount( - - {}} /> - - ) + render( + + {}} /> + ); - expect(casesMock.ui.getRecentCases).not.toHaveBeenCalled(); + await waitFor(() => { + expect(casesMock.ui.getRecentCases).not.toHaveBeenCalled(); + }); }); it('does render the recently created cases section when the user has read permissions', async () => { casesMock.helpers.canUseCases.mockReturnValue(readCasesPermissions()); - await waitFor(() => - mount( - - {}} /> - - ) + render( + + {}} /> + ); - expect(casesMock.ui.getRecentCases).toHaveBeenCalled(); + await waitFor(() => { + expect(casesMock.ui.getRecentCases).toHaveBeenCalled(); + }); + }); + + it('does not render recent timelines for users with insufficient privileges', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: {}, + }); + + render( + + {}} /> + + ); + + expect(screen.queryByTestId('recent-timelines-container')).not.toBeInTheDocument(); + }); + + it('does render recent timelines for users with sufficient privileges', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { read: true }, + }); + + render( + + {}} /> + + ); + + expect(screen.queryByTestId('recent-timelines-container')).toBeInTheDocument(); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/sidebar/sidebar.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/sidebar/sidebar.tsx index 501e03a65cb02..10d3e40bb926e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/sidebar/sidebar.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/sidebar/sidebar.tsx @@ -17,6 +17,7 @@ import { import { Filters as RecentTimelinesFilters } from '../recent_timelines/filters'; import { StatefulRecentTimelines } from '../recent_timelines'; import { StatefulNewsFeed } from '../../../common/components/news_feed'; +import { useUserPrivileges } from '../../../common/components/user_privileges'; import type { FilterMode as RecentTimelinesFilterMode } from '../recent_timelines/types'; import { SidebarHeader } from '../../../common/components/sidebar_header'; @@ -35,6 +36,9 @@ export const Sidebar = React.memo<{ setRecentTimelinesFilterBy: (filterBy: RecentTimelinesFilterMode) => void; }>(({ recentTimelinesFilterBy, setRecentTimelinesFilterBy }) => { const { cases } = useKibana().services; + const { + timelinePrivileges: { read: canSeeTimelines }, + } = useUserPrivileges(); const recentTimelinesFilters = useMemo( () => ( )} - - {recentTimelinesFilters} - - + {canSeeTimelines && ( + + {recentTimelinesFilters} + + + )} { private config: SecuritySolutionUiConfigType; @@ -438,7 +439,10 @@ export class Plugin implements IPlugin ({ status: AppStatus.inaccessible, visibleIn: [], diff --git a/x-pack/solutions/security/plugins/security_solution/public/rules/links.ts b/x-pack/solutions/security/plugins/security_solution/public/rules/links.ts index ba4280739bbe6..28f44585d3037 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/rules/links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/rules/links.ts @@ -13,7 +13,7 @@ import { RULES_CREATE_PATH, RULES_LANDING_PATH, RULES_PATH, - SERVER_APP_ID, + SECURITY_FEATURE_ID, } from '../../common/constants'; import { ADD_RULES, @@ -38,7 +38,7 @@ export const links: LinkItem = { hideTimeline: true, skipUrlState: true, globalNavPosition: 2, - capabilities: [`${SERVER_APP_ID}.show`], + capabilities: [`${SECURITY_FEATURE_ID}.show`], links: [ { id: SecurityPageName.rules, @@ -79,7 +79,7 @@ export const links: LinkItem = { }), landingIcon: IconConsoleCloud, path: EXCEPTIONS_PATH, - capabilities: [`${SERVER_APP_ID}.showEndpointExceptions`], + capabilities: [`${SECURITY_FEATURE_ID}.showEndpointExceptions`], skipUrlState: true, hideTimeline: true, globalSearchKeywords: [ @@ -100,7 +100,7 @@ export const links: LinkItem = { } ), path: COVERAGE_OVERVIEW_PATH, - capabilities: [`${SERVER_APP_ID}.show`], + capabilities: [`${SECURITY_FEATURE_ID}.show`], globalSearchKeywords: [ i18n.translate('xpack.securitySolution.appLinks.coverageOverviewDashboard', { defaultMessage: 'MITRE ATT&CK Coverage', diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/links.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/links.ts index 4ea47d829d794..29d374713cf17 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/links.ts @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n'; import { SecurityPageName, - SERVER_APP_ID, + SECURITY_FEATURE_ID, SIEM_MIGRATIONS_RULES_PATH, } from '../../common/constants'; import { SIEM_MIGRATIONS_RULES } from '../app/translations'; @@ -23,7 +23,7 @@ export const siemMigrationsLinks: LinkItem = { }), landingIcon: SiemMigrationsIcon, path: SIEM_MIGRATIONS_RULES_PATH, - capabilities: [`${SERVER_APP_ID}.show`], + capabilities: [`${SECURITY_FEATURE_ID}.show`], skipUrlState: true, hideTimeline: true, globalSearchKeywords: [ diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/api/index.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/api/index.ts index 148417ce3273e..5ebf30fda0c56 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/api/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/api/index.ts @@ -7,6 +7,7 @@ import { replaceParams } from '@kbn/openapi-common/shared'; +import type { RuleMigrationFilters } from '../../../../common/siem_migrations/types'; import type { UpdateRuleMigrationData } from '../../../../common/siem_migrations/model/rule_migration.gen'; import type { LangSmithOptions } from '../../../../common/siem_migrations/model/common.gen'; import { KibanaServices } from '../../../common/lib/kibana'; @@ -15,7 +16,6 @@ import type { SiemMigrationRetryFilter } from '../../../../common/siem_migration import { SIEM_RULE_MIGRATIONS_PATH, SIEM_RULE_MIGRATIONS_ALL_STATS_PATH, - SIEM_RULE_MIGRATION_INSTALL_TRANSLATED_PATH, SIEM_RULE_MIGRATION_INSTALL_PATH, SIEM_RULE_MIGRATION_PATH, SIEM_RULE_MIGRATION_START_PATH, @@ -32,7 +32,6 @@ import type { GetAllStatsRuleMigrationResponse, GetRuleMigrationResponse, GetRuleMigrationTranslationStatsResponse, - InstallTranslatedMigrationRulesResponse, InstallMigrationRulesResponse, StartRuleMigrationRequestBody, GetRuleMigrationStatsResponse, @@ -176,22 +175,8 @@ export interface GetRuleMigrationParams { sortField?: string; /** Optional direction to sort results by */ sortDirection?: 'asc' | 'desc'; - /** Optional search term to filter documents */ - searchTerm?: string; - /** Optional rules ids to filter documents */ - ids?: string[]; - /** Optional attribute to retrieve prebuilt migration rules */ - isPrebuilt?: boolean; - /** Optional attribute to retrieve installed migration rules */ - isInstalled?: boolean; - /** Optional attribute to retrieve fully translated migration rules */ - isFullyTranslated?: boolean; - /** Optional attribute to retrieve partially translated migration rules */ - isPartiallyTranslated?: boolean; - /** Optional attribute to retrieve untranslated migration rules */ - isUntranslatable?: boolean; - /** Optional attribute to retrieve failed migration rules */ - isFailed?: boolean; + /** Optional parameter to filter documents */ + filters?: RuleMigrationFilters; /** Optional AbortSignal for cancelling request */ signal?: AbortSignal; } @@ -202,14 +187,7 @@ export const getRuleMigrations = async ({ perPage, sortField, sortDirection, - searchTerm, - ids, - isPrebuilt, - isInstalled, - isFullyTranslated, - isPartiallyTranslated, - isUntranslatable, - isFailed, + filters, signal, }: GetRuleMigrationParams): Promise => { return KibanaServices.get().http.get( @@ -221,14 +199,14 @@ export const getRuleMigrations = async ({ per_page: perPage, sort_field: sortField, sort_direction: sortDirection, - search_term: searchTerm, - ids, - is_prebuilt: isPrebuilt, - is_installed: isInstalled, - is_fully_translated: isFullyTranslated, - is_partially_translated: isPartiallyTranslated, - is_untranslatable: isUntranslatable, - is_failed: isFailed, + search_term: filters?.searchTerm, + ids: filters?.ids, + is_prebuilt: filters?.prebuilt, + is_installed: filters?.installed, + is_fully_translated: filters?.fullyTranslated, + is_partially_translated: filters?.partiallyTranslated, + is_untranslatable: filters?.untranslatable, + is_failed: filters?.failed, }, signal, } @@ -258,7 +236,7 @@ export interface InstallRulesParams { /** `id` of the migration to install rules for */ migrationId: string; /** The rule ids to install */ - ids: string[]; + ids?: string[]; /** Optional indicator to enable the installed rule */ enabled?: boolean; /** Optional AbortSignal for cancelling request */ @@ -277,23 +255,6 @@ export const installMigrationRules = async ({ ); }; -export interface InstallTranslatedRulesParams { - /** `id` of the migration to install rules for */ - migrationId: string; - /** Optional AbortSignal for cancelling request */ - signal?: AbortSignal; -} -/** Installs all the translated rules for a specific migration. */ -export const installTranslatedMigrationRules = async ({ - migrationId, - signal, -}: InstallTranslatedRulesParams): Promise => { - return KibanaServices.get().http.post( - replaceParams(SIEM_RULE_MIGRATION_INSTALL_TRANSLATED_PATH, { migration_id: migrationId }), - { version: '1', signal } - ); -}; - export interface GetRuleMigrationsPrebuiltRulesParams { /** `id` of the migration to install rules for */ migrationId: string; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/index.tsx index 819750b619741..353b42a5f1337 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/index.tsx @@ -101,7 +101,7 @@ export const MigrationRuleDetailsFlyout: React.FC { - if (!ruleMigration || isLoading) { + if (isLoading) { return; } setIsUpdating(true); @@ -139,13 +139,11 @@ export const MigrationRuleDetailsFlyout: React.FC - {ruleMigration && ( - - )} + ), }), @@ -242,7 +240,7 @@ export const MigrationRuleDetailsFlyout: React.FC

{ruleDetailsToOverview?.name ?? - ruleMigration?.original_rule.title ?? + ruleMigration.original_rule.title ?? i18n.UNKNOWN_MIGRATION_RULE_TITLE}

diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/summary/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/summary/index.tsx index ab5d9deb3852d..e046b7957023f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/summary/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/summary/index.tsx @@ -10,10 +10,8 @@ import type { EuiCommentProps } from '@elastic/eui'; import { EuiCommentList, EuiMarkdownFormat, EuiSpacer } from '@elastic/eui'; import moment from 'moment'; import { AssistantAvatar } from '@kbn/ai-assistant-icon'; -import { - RuleMigrationStatusEnum, - type RuleMigration, -} from '../../../../../../../common/siem_migrations/model/rule_migration.gen'; +import { type RuleMigration } from '../../../../../../../common/siem_migrations/model/rule_migration.gen'; +import { RuleTranslationResult } from '../../../../../../../common/siem_migrations/constants'; import * as i18n from './translations'; interface SummaryTabProps { @@ -33,8 +31,8 @@ export const SummaryTab: React.FC = React.memo(({ ruleMigration timelineAvatarAriaLabel: i18n.ASSISTANT_USERNAME, timelineAvatar: , event: - ruleMigration.status === RuleMigrationStatusEnum.failed - ? i18n.COMMENT_EVENT_FAILED + ruleMigration.translation_result === RuleTranslationResult.UNTRANSLATABLE + ? i18n.COMMENT_EVENT_UNTRANSLATABLE : i18n.COMMENT_EVENT_TRANSLATED, timestamp, children: {comment}, diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/summary/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/summary/translations.ts index 87d0840ac0efb..78f5066b45916 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/summary/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/summary/translations.ts @@ -28,8 +28,8 @@ export const COMMENT_EVENT_TRANSLATED = i18n.translate( } ); -export const COMMENT_EVENT_FAILED = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.translationDetails.summaryTab.commentEvent.failedLabel', +export const COMMENT_EVENT_UNTRANSLATABLE = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.translationDetails.summaryTab.commentEvent.untranslatableLabel', { defaultMessage: 'failed to translate', } diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/index.tsx index 8ad5c9af9a62e..182fb3c9fc048 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/index.tsx @@ -106,7 +106,7 @@ export const TranslationTab: React.FC = React.memo( {}} - onClickAriaLabel={'Click to update translation status'} + onClickAriaLabel={'Translation status badge'} > {isInstalled ? i18n.INSTALLED_LABEL diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/migration_rule_query.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/migration_rule_query.tsx index 9b41d43d1c0ec..0aeb4042d1b86 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/migration_rule_query.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/migration_rule_query.tsx @@ -116,7 +116,12 @@ export const MigrationRuleQuery: React.FC = React.memo(

{ruleName}

- + {query} diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/translations.ts index 468e8304c62bb..925c94d05ec12 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/translations.ts @@ -96,7 +96,7 @@ export const CALLOUT_PARTIALLY_TRANSLATED_RULE_DESCRIPTION = i18n.translate( 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.partiallyTranslatedRuleCalloutDescription', { defaultMessage: - 'To save this rule, finish the query and define its severity. If you need help, please contact Elastic support.', + 'To save this rule, finish writing the query. If you need help, please contact Elastic support.', } ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/filters/author.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/filters/author.tsx index ac5a1f449c407..fd12fc3185bde 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/filters/author.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/filters/author.tsx @@ -9,7 +9,7 @@ import React, { useCallback, useMemo, useState } from 'react'; import type { EuiSelectableOption } from '@elastic/eui'; import { EuiFilterButton, EuiPopover, EuiSelectable } from '@elastic/eui'; import type { EuiSelectableOnChangeEvent } from '@elastic/eui/src/components/selectable/selectable'; -import { AuthorFilter } from '../../../../../../common/siem_migrations/constants'; +import { AuthorFilter } from '../../../types'; import * as i18n from './translations'; const AUTHOR_FILTER_POPOVER_WIDTH = 150; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/filters/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/filters/index.tsx index a02f5aea5b21d..903147960a9b4 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/filters/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/filters/index.tsx @@ -7,18 +7,10 @@ import React, { useCallback } from 'react'; import { EuiFilterGroup } from '@elastic/eui'; -import type { - AuthorFilter, - StatusFilter, -} from '../../../../../../common/siem_migrations/constants'; +import type { AuthorFilter, FilterOptions, StatusFilter } from '../../../types'; import { StatusFilterButton } from './status'; import { AuthorFilterButton } from './author'; -export interface FilterOptions { - status?: StatusFilter; - author?: AuthorFilter; -} - export interface MigrationRulesFilterProps { filterOptions?: FilterOptions; onFilterOptionsChanged: (filterOptions?: FilterOptions) => void; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/filters/status.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/filters/status.tsx index fe23de69ef816..c8f35426ab928 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/filters/status.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/filters/status.tsx @@ -9,12 +9,10 @@ import React, { useCallback, useState } from 'react'; import type { EuiSelectableOption } from '@elastic/eui'; import { EuiFilterButton, EuiPopover, EuiSelectable } from '@elastic/eui'; import type { EuiSelectableOnChangeEvent } from '@elastic/eui/src/components/selectable/selectable'; -import { - RuleTranslationResult, - StatusFilter, -} from '../../../../../../common/siem_migrations/constants'; -import * as i18n from './translations'; +import { RuleTranslationResult } from '../../../../../../common/siem_migrations/constants'; import { convertTranslationResultIntoText } from '../../../utils/translation_results'; +import { StatusFilter } from '../../../types'; +import * as i18n from './translations'; const STATUS_FILTER_POPOVER_WIDTH = 250; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/helpers.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/helpers.ts deleted file mode 100644 index 0d6590b90180c..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/helpers.ts +++ /dev/null @@ -1,25 +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 { AuthorFilter, StatusFilter } from '../../../../../common/siem_migrations/constants'; -import type { FilterOptions } from './filters'; - -export const convertFilterOptions = (filterOptions?: FilterOptions) => { - return { - ...(filterOptions?.author === AuthorFilter.ELASTIC ? { isPrebuilt: true } : {}), - ...(filterOptions?.author === AuthorFilter.CUSTOM ? { isPrebuilt: false } : {}), - ...(filterOptions?.status === StatusFilter.FAILED ? { isFailed: true } : {}), - ...(filterOptions?.status === StatusFilter.INSTALLED ? { isInstalled: true } : {}), - ...(filterOptions?.status === StatusFilter.TRANSLATED - ? { isInstalled: false, isFullyTranslated: true } - : {}), - ...(filterOptions?.status === StatusFilter.PARTIALLY_TRANSLATED - ? { isPartiallyTranslated: true } - : {}), - ...(filterOptions?.status === StatusFilter.UNTRANSLATABLE ? { isUntranslatable: true } : {}), - }; -}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/index.tsx index b8340beaf55e7..30c2a8e0b538a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/index.tsx @@ -27,7 +27,6 @@ import { useMigrationRulesTableColumns } from '../../hooks/use_migration_rules_t import { useMigrationRuleDetailsFlyout } from '../../hooks/use_migration_rule_preview_flyout'; import { useInstallMigrationRules } from '../../logic/use_install_migration_rules'; import { useGetMigrationRules } from '../../logic/use_get_migration_rules'; -import { useInstallTranslatedMigrationRules } from '../../logic/use_install_translated_migration_rules'; import { useGetMigrationTranslationStats } from '../../logic/use_get_migration_translation_stats'; import { useGetMigrationPrebuiltRules } from '../../logic/use_get_migration_prebuilt_rules'; import * as logicI18n from '../../logic/translations'; @@ -39,9 +38,9 @@ import { } from '../../../../../common/siem_migrations/constants'; import * as i18n from './translations'; import { useStartMigration } from '../../service/hooks/use_start_migration'; -import type { FilterOptions } from './filters'; +import type { FilterOptions } from '../../types'; import { MigrationRulesFilter } from './filters'; -import { convertFilterOptions } from './helpers'; +import { convertFilterOptions } from './utils/filters'; const DEFAULT_PAGE_SIZE = 10; const DEFAULT_SORT_FIELD = 'translation_result'; @@ -100,8 +99,10 @@ export const MigrationRulesTable: React.FC = React.mem perPage: pageSize, sortField, sortDirection, - searchTerm, - ...convertFilterOptions(filterOptions), + filters: { + searchTerm, + ...convertFilterOptions(filterOptions), + }, }); const [selectedRuleMigrations, setSelectedRuleMigrations] = useState([]); @@ -158,13 +159,11 @@ export const MigrationRulesTable: React.FC = React.mem }, []); const { mutateAsync: installMigrationRules } = useInstallMigrationRules(migrationId); - const { mutateAsync: installTranslatedMigrationRules } = - useInstallTranslatedMigrationRules(migrationId); const { startMigration, isLoading: isRetryLoading } = useStartMigration(refetchData); const [isTableLoading, setTableLoading] = useState(false); const installSingleRule = useCallback( - async (migrationRule: RuleMigration, enabled = false) => { + async (migrationRule: RuleMigration, enabled?: boolean) => { setTableLoading(true); try { await installMigrationRules({ ids: [migrationRule.id], enabled }); @@ -178,7 +177,7 @@ export const MigrationRulesTable: React.FC = React.mem ); const installSelectedRule = useCallback( - async (enabled = false) => { + async (enabled?: boolean) => { setTableLoading(true); try { await installMigrationRules({ @@ -196,30 +195,30 @@ export const MigrationRulesTable: React.FC = React.mem ); const installTranslatedRules = useCallback( - async (enable?: boolean) => { + async (enabled?: boolean) => { setTableLoading(true); try { - await installTranslatedMigrationRules(); + await installMigrationRules({ enabled }); } catch (error) { addError(error, { title: logicI18n.INSTALL_MIGRATION_RULES_FAILURE }); } finally { setTableLoading(false); } }, - [addError, installTranslatedMigrationRules] + [addError, installMigrationRules] ); const reprocessFailedRules = useCallback(async () => { startMigration(migrationId, SiemMigrationRetryFilter.FAILED); }, [migrationId, startMigration]); - const isLoading = - isStatsLoading || isPrebuiltRulesLoading || isDataLoading || isTableLoading || isRetryLoading; + const isRulesLoading = + isPrebuiltRulesLoading || isDataLoading || isTableLoading || isRetryLoading; const ruleActionsFactory = useCallback( (ruleMigration: RuleMigration, closeRulePreview: () => void) => { const canMigrationRuleBeInstalled = - !isLoading && + !isRulesLoading && !ruleMigration.elastic_rule?.id && ruleMigration.translation_result === RuleTranslationResult.FULL; return ( @@ -254,45 +253,39 @@ export const MigrationRulesTable: React.FC = React.mem ); }, - [installSingleRule, isLoading] + [installSingleRule, isRulesLoading] ); const getMigrationRuleData = useCallback( (ruleId: string) => { - if (!isLoading && ruleMigrations.length) { + if (!isRulesLoading && ruleMigrations.length) { const ruleMigration = ruleMigrations.find((item) => item.id === ruleId); let matchedPrebuiltRule: RuleResponse | undefined; - const relatedIntegrations: RelatedIntegration[] = []; + let relatedIntegrations: RelatedIntegration[] = []; if (ruleMigration) { // Find matched prebuilt rule if any and prioritize its installed version - const matchedPrebuiltRuleVersion = ruleMigration.elastic_rule?.prebuilt_rule_id - ? prebuiltRules[ruleMigration.elastic_rule.prebuilt_rule_id] - : undefined; - matchedPrebuiltRule = - matchedPrebuiltRuleVersion?.current ?? matchedPrebuiltRuleVersion?.target; + const prebuiltRuleId = ruleMigration.elastic_rule?.prebuilt_rule_id; + const prebuiltRuleVersions = prebuiltRuleId ? prebuiltRules[prebuiltRuleId] : undefined; + matchedPrebuiltRule = prebuiltRuleVersions?.current ?? prebuiltRuleVersions?.target; - if (integrations) { - if (matchedPrebuiltRule?.related_integrations) { - relatedIntegrations.push(...matchedPrebuiltRule.related_integrations); - } else if (ruleMigration.elastic_rule?.integration_id) { - const integration = integrations[ruleMigration.elastic_rule.integration_id]; - if (integration) { - relatedIntegrations.push(integration); - } - } + const integrationIds = ruleMigration.elastic_rule?.integration_ids; + if (integrations && integrationIds) { + relatedIntegrations = integrationIds + .map((integrationId) => integrations[integrationId]) + .filter((integration) => integration != null); } } return { ruleMigration, matchedPrebuiltRule, relatedIntegrations, isIntegrationsLoading }; } }, - [integrations, isIntegrationsLoading, isLoading, prebuiltRules, ruleMigrations] + [integrations, isIntegrationsLoading, isRulesLoading, prebuiltRules, ruleMigrations] ); const { migrationRuleDetailsFlyout: rulePreviewFlyout, openMigrationRuleDetails: openRulePreview, } = useMigrationRuleDetailsFlyout({ - isLoading, + isLoading: isRulesLoading, getMigrationRuleData, ruleActionsFactory, }); @@ -307,7 +300,7 @@ export const MigrationRulesTable: React.FC = React.mem return ( <> @@ -331,7 +324,7 @@ export const MigrationRulesTable: React.FC = React.mem
= { + [AuthorFilter.ELASTIC]: { prebuilt: true }, + [AuthorFilter.CUSTOM]: { prebuilt: false }, +}; + +const STATUS_FILTERS: Record = { + [StatusFilter.FAILED]: { failed: true }, + [StatusFilter.INSTALLED]: { installed: true }, + [StatusFilter.TRANSLATED]: { installed: false, fullyTranslated: true }, + [StatusFilter.PARTIALLY_TRANSLATED]: { partiallyTranslated: true }, + [StatusFilter.UNTRANSLATABLE]: { untranslatable: true }, +}; + +export const convertFilterOptions = (filterOptions?: FilterOptions) => { + const filters: RuleMigrationFilters = {}; + if (filterOptions?.author) { + Object.assign(filters, AUTHOR_FILTERS[filterOptions.author]); + } + if (filterOptions?.status) { + Object.assign(filters, STATUS_FILTERS[filterOptions.status]); + } + return filters; +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/actions.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/actions.tsx index a5c67403f4458..c72001e394f28 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/actions.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/actions.tsx @@ -6,7 +6,8 @@ */ import React from 'react'; -import { EuiLink } from '@elastic/eui'; +import { EuiHorizontalRule, EuiLink, EuiText } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; import { SecuritySolutionLinkAnchor } from '../../../../common/components/links'; import { RuleTranslationResult, @@ -17,6 +18,7 @@ import { SecurityPageName } from '../../../../../common'; import { type RuleMigration } from '../../../../../common/siem_migrations/model/rule_migration.gen'; import * as i18n from './translations'; import { type TableColumn } from './constants'; +import { TableHeader } from './header'; interface ActionNameProps { disableActions?: boolean; @@ -91,7 +93,34 @@ export const createActionsColumn = ({ }: CreateActionsColumnProps): TableColumn => { return { field: 'elastic_rule', - name: i18n.COLUMN_ACTIONS, + name: ( + , + title: ( + +

+ {i18n.COLUMN_ACTIONS} + +

+
+ ), + view: {i18n.ACTIONS_VIEW_LABEL}, + install: {i18n.ACTIONS_INSTALL_LABEL}, + edit: {i18n.ACTIONS_EDIT_LABEL}, + }} + /> + } + /> + ), render: (_, rule: RuleMigration) => { return ( { return ( @@ -30,7 +32,32 @@ const Author = ({ isPrebuiltRule }: { isPrebuiltRule: boolean }) => { export const createAuthorColumn = (): TableColumn => { return { field: 'elastic_rule.prebuilt_rule_id', - name: i18n.COLUMN_AUTHOR, + name: ( + , + title: ( + +

+ {i18n.COLUMN_AUTHOR} + +

+
+ ), + elastic: {i18n.ELASTIC_AUTHOR_TITLE}, + custom: {i18n.CUSTOM_AUTHOR_TITLE}, + }} + /> + } + /> + ), render: (_, rule: RuleMigration) => { return rule.status === SiemMigrationStatus.FAILED ? ( <>{COLUMN_EMPTY_VALUE} diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/header/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/header/index.tsx new file mode 100644 index 0000000000000..c23e8f7d3db2f --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/header/index.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 React from 'react'; + +import { EuiToolTip, EuiIcon } from '@elastic/eui'; + +interface TableHeaderProps { + title: string; + tooltipContent?: React.ReactNode; +} + +export const TableHeader: React.FC = React.memo(({ title, tooltipContent }) => { + return ( + + <> + {title} +   + + + + ); +}); +TableHeader.displayName = 'TableHeader'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/integrations.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/integrations.tsx index 43b7086c9814c..2f8dcb4b7a38e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/integrations.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/integrations.tsx @@ -6,12 +6,14 @@ */ import React from 'react'; -import { EuiLoadingSpinner } from '@elastic/eui'; +import { EuiHorizontalRule, EuiLoadingSpinner, EuiText } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; import type { RelatedIntegration } from '../../../../../common/api/detection_engine'; import { IntegrationsPopover } from '../../../../detections/components/rules/related_integrations/integrations_popover'; import type { RuleMigration } from '../../../../../common/siem_migrations/model/rule_migration.gen'; import * as i18n from './translations'; import type { TableColumn } from './constants'; +import { TableHeader } from './header'; export const createIntegrationsColumn = ({ getMigrationRuleData, @@ -21,8 +23,28 @@ export const createIntegrationsColumn = ({ ) => { relatedIntegrations?: RelatedIntegration[]; isIntegrationsLoading?: boolean } | undefined; }): TableColumn => { return { - field: 'elastic_rule.integration_id', - name: i18n.COLUMN_INTEGRATIONS, + field: 'elastic_rule.integration_ids', + name: ( + +

+ {i18n.COLUMN_INTEGRATIONS} + +

+ + ), + }} + /> + } + /> + ), render: (_, rule: RuleMigration) => { const migrationRuleData = getMigrationRuleData(rule.id); if (migrationRuleData?.isIntegrationsLoading) { diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/risk_score.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/risk_score.tsx index d0584cc14e2af..938d86dde01b0 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/risk_score.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/risk_score.tsx @@ -8,22 +8,17 @@ import React from 'react'; import { EuiText } from '@elastic/eui'; import { type RuleMigration } from '../../../../../common/siem_migrations/model/rule_migration.gen'; -import { - DEFAULT_TRANSLATION_RISK_SCORE, - SiemMigrationStatus, -} from '../../../../../common/siem_migrations/constants'; +import { SiemMigrationStatus } from '../../../../../common/siem_migrations/constants'; import * as i18n from './translations'; import { COLUMN_EMPTY_VALUE, type TableColumn } from './constants'; export const createRiskScoreColumn = (): TableColumn => { return { - field: 'risk_score', + field: 'elastic_rule.risk_score', name: i18n.COLUMN_RISK_SCORE, - render: (_, rule: RuleMigration) => ( + render: (riskScore, rule: RuleMigration) => ( - {rule.status === SiemMigrationStatus.FAILED - ? COLUMN_EMPTY_VALUE - : DEFAULT_TRANSLATION_RISK_SCORE} + {rule.status === SiemMigrationStatus.FAILED ? COLUMN_EMPTY_VALUE : riskScore} ), sortable: true, diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/severity.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/severity.tsx index 2a97288eef267..6911e23a421fb 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/severity.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/severity.tsx @@ -7,20 +7,40 @@ import React from 'react'; import type { Severity } from '@kbn/securitysolution-io-ts-alerting-types'; +import { EuiHorizontalRule, EuiText } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; import { type RuleMigration } from '../../../../../common/siem_migrations/model/rule_migration.gen'; -import { - DEFAULT_TRANSLATION_SEVERITY, - SiemMigrationStatus, -} from '../../../../../common/siem_migrations/constants'; +import { SiemMigrationStatus } from '../../../../../common/siem_migrations/constants'; import { SeverityBadge } from '../../../../common/components/severity_badge'; import { COLUMN_EMPTY_VALUE, type TableColumn } from './constants'; import * as i18n from './translations'; +import { TableHeader } from './header'; export const createSeverityColumn = (): TableColumn => { return { field: 'elastic_rule.severity', - name: i18n.COLUMN_SEVERITY, - render: (value: Severity = DEFAULT_TRANSLATION_SEVERITY, rule: RuleMigration) => + name: ( + +

+ {i18n.COLUMN_SEVERITY} + +

+ + ), + }} + /> + } + /> + ), + render: (value: Severity, rule: RuleMigration) => rule.status === SiemMigrationStatus.FAILED ? ( <>{COLUMN_EMPTY_VALUE} ) : ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/status.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/status.tsx index 2936878c93b8b..0a8d78f3aa812 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/status.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/status.tsx @@ -6,15 +6,53 @@ */ import React from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { EuiHorizontalRule, EuiText } from '@elastic/eui'; +import { RuleTranslationResult } from '../../../../../common/siem_migrations/constants'; import type { RuleMigration } from '../../../../../common/siem_migrations/model/rule_migration.gen'; import * as i18n from './translations'; import type { TableColumn } from './constants'; import { StatusBadge } from '../status_badge'; +import { TableHeader } from './header'; +import { convertTranslationResultIntoText } from '../../utils/translation_results'; export const createStatusColumn = (): TableColumn => { return { field: 'translation_result', - name: i18n.COLUMN_STATUS, + name: ( + , + title: ( + +

+ {i18n.STATUS_TOOLTIP_TITLE} + +

+
+ ), + installed: {i18n.INSTALLED_STATUS_TITLE}, + translated: {convertTranslationResultIntoText(RuleTranslationResult.FULL)}, + partiallyTranslated: ( + {convertTranslationResultIntoText(RuleTranslationResult.PARTIAL)} + ), + notTranslated: ( + {convertTranslationResultIntoText(RuleTranslationResult.UNTRANSLATABLE)} + ), + }} + /> + } + /> + ), render: (_, rule: RuleMigration) => , sortable: true, truncateText: true, diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/translations.ts index e16b4b334eb75..a38a765d36f54 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/translations.ts @@ -97,3 +97,17 @@ export const COLUMN_INTEGRATIONS = i18n.translate( defaultMessage: 'Integrations', } ); + +export const STATUS_TOOLTIP_TITLE = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tableColumn.statusTooltipTitle', + { + defaultMessage: 'Translation Status legend', + } +); + +export const INSTALLED_STATUS_TITLE = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tableColumn.installedStatusTitle', + { + defaultMessage: 'Installed', + } +); diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/status_badge/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/status_badge/index.tsx index 867c5034ba9eb..428dbf522f815 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/status_badge/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/status_badge/index.tsx @@ -49,8 +49,11 @@ export const StatusBadge: React.FC = React.memo( // Failed if (migrationRule.status === RuleMigrationStatusEnum.failed) { + const tooltipMessage = migrationRule.comments?.length + ? migrationRule.comments[0] + : i18n.RULE_STATUS_FAILED; return ( - + diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/logic/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/logic/translations.ts index e83293ec61097..777f2a01b3081 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/logic/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/logic/translations.ts @@ -28,6 +28,12 @@ export const GET_MIGRATION_TRANSLATION_STATS_FAILURE = i18n.translate( } ); +export const INSTALL_MIGRATION_RULES_SUCCESS = (succeeded: number) => + i18n.translate('xpack.securitySolution.siemMigrations.rules.installMigrationRulesSuccess', { + defaultMessage: '{succeeded, plural, one {# rule} other {# rules}} installed successfully.', + values: { succeeded }, + }); + export const INSTALL_MIGRATION_RULES_FAILURE = i18n.translate( 'xpack.securitySolution.siemMigrations.rules.installMigrationRulesFailDescription', { diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/logic/use_get_migration_rules.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/logic/use_get_migration_rules.ts index 07fff1e986373..66e934a8bf8e9 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/logic/use_get_migration_rules.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/logic/use_get_migration_rules.ts @@ -8,6 +8,7 @@ import { useQuery, useQueryClient } from '@tanstack/react-query'; import { replaceParams } from '@kbn/openapi-common/shared'; import { useCallback } from 'react'; +import type { RuleMigrationFilters } from '../../../../common/siem_migrations/types'; import { SIEM_RULE_MIGRATION_PATH } from '../../../../common/siem_migrations/constants'; import { useAppToasts } from '../../../common/hooks/use_app_toasts'; import * as i18n from './translations'; @@ -20,14 +21,7 @@ export const useGetMigrationRules = (params: { perPage?: number; sortField?: string; sortDirection?: 'asc' | 'desc'; - searchTerm?: string; - ids?: string[]; - isPrebuilt?: boolean; - isInstalled?: boolean; - isFullyTranslated?: boolean; - isPartiallyTranslated?: boolean; - isUntranslatable?: boolean; - isFailed?: boolean; + filters?: RuleMigrationFilters; }) => { const { addError } = useAppToasts(); diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/logic/use_install_migration_rules.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/logic/use_install_migration_rules.ts index b69be3b86d11c..b8061c6be6178 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/logic/use_install_migration_rules.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/logic/use_install_migration_rules.ts @@ -17,15 +17,18 @@ import { installMigrationRules } from '../api'; export const INSTALL_MIGRATION_RULES_MUTATION_KEY = ['POST', SIEM_RULE_MIGRATION_INSTALL_PATH]; export const useInstallMigrationRules = (migrationId: string) => { - const { addError } = useAppToasts(); + const { addError, addSuccess } = useAppToasts(); const invalidateGetRuleMigrations = useInvalidateGetMigrationRules(); const invalidateGetMigrationTranslationStats = useInvalidateGetMigrationTranslationStats(); - return useMutation( - ({ ids, enabled = false }) => installMigrationRules({ migrationId, ids, enabled }), + return useMutation( + ({ ids, enabled }) => installMigrationRules({ migrationId, ids, enabled }), { mutationKey: INSTALL_MIGRATION_RULES_MUTATION_KEY, + onSuccess: ({ installed }) => { + addSuccess(i18n.INSTALL_MIGRATION_RULES_SUCCESS(installed)); + }, onError: (error) => { addError(error, { title: i18n.INSTALL_MIGRATION_RULES_FAILURE }); }, diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/logic/use_install_translated_migration_rules.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/logic/use_install_translated_migration_rules.ts deleted file mode 100644 index bcce981a4cfb5..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/logic/use_install_translated_migration_rules.ts +++ /dev/null @@ -1,41 +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 { useMutation } from '@tanstack/react-query'; -import type { InstallTranslatedMigrationRulesResponse } from '../../../../common/siem_migrations/model/api/rules/rule_migration.gen'; -import { SIEM_RULE_MIGRATION_INSTALL_TRANSLATED_PATH } from '../../../../common/siem_migrations/constants'; -import { useAppToasts } from '../../../common/hooks/use_app_toasts'; -import * as i18n from './translations'; -import { useInvalidateGetMigrationRules } from './use_get_migration_rules'; -import { useInvalidateGetMigrationTranslationStats } from './use_get_migration_translation_stats'; -import { installTranslatedMigrationRules } from '../api'; - -export const INSTALL_ALL_MIGRATION_RULES_MUTATION_KEY = [ - 'POST', - SIEM_RULE_MIGRATION_INSTALL_TRANSLATED_PATH, -]; - -export const useInstallTranslatedMigrationRules = (migrationId: string) => { - const { addError } = useAppToasts(); - - const invalidateGetRuleMigrations = useInvalidateGetMigrationRules(); - const invalidateGetMigrationTranslationStats = useInvalidateGetMigrationTranslationStats(); - - return useMutation( - () => installTranslatedMigrationRules({ migrationId }), - { - mutationKey: INSTALL_ALL_MIGRATION_RULES_MUTATION_KEY, - onError: (error) => { - addError(error, { title: i18n.INSTALL_MIGRATION_RULES_FAILURE }); - }, - onSettled: () => { - invalidateGetRuleMigrations(migrationId); - invalidateGetMigrationTranslationStats(migrationId); - }, - } - ); -}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/pages/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/pages/index.tsx index c49938e3b69eb..c31048bf08bcf 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/pages/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/pages/index.tsx @@ -7,7 +7,7 @@ import React, { useCallback, useEffect, useMemo } from 'react'; -import { EuiSkeletonLoading, EuiSkeletonText, EuiSkeletonTitle } from '@elastic/eui'; +import { EuiSkeletonLoading, EuiSkeletonText, EuiSkeletonTitle, EuiSpacer } from '@elastic/eui'; import type { RouteComponentProps } from 'react-router-dom'; import type { RelatedIntegration } from '../../../../common/api/detection_engine'; import { SiemMigrationTaskStatus } from '../../../../common/siem_migrations/constants'; @@ -29,6 +29,7 @@ import { useInvalidateGetMigrationRules } from '../logic/use_get_migration_rules import { useInvalidateGetMigrationTranslationStats } from '../logic/use_get_migration_translation_stats'; import { useGetIntegrations } from '../service/hooks/use_get_integrations'; import { PageTitle } from './page_title'; +import { RuleMigrationsUploadMissingPanel } from '../components/migration_status_panels/upload_missing_panel'; type MigrationRulesPageProps = RouteComponentProps<{ migrationId?: string }>; @@ -99,19 +100,24 @@ export const MigrationRulesPage: React.FC = React.memo( if (!migrationId || !migrationStats) { return ; } - if (migrationStats.status === SiemMigrationTaskStatus.FINISHED) { - return ( - - ); - } return ( <> + {migrationStats.status === SiemMigrationTaskStatus.FINISHED && ( + <> + + + + + )} {migrationStats.status === SiemMigrationTaskStatus.READY && ( )} diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/types.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/types.ts index bcc11327d1051..4f6d088a135f7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/types.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/types.ts @@ -13,3 +13,21 @@ export interface RuleMigrationStats extends RuleMigrationTaskStats { /** The sequential number of the migration */ number: number; } + +export enum AuthorFilter { + ELASTIC = 'elastic', + CUSTOM = 'custom', +} + +export enum StatusFilter { + INSTALLED = 'installed', + TRANSLATED = 'translated', + PARTIALLY_TRANSLATED = 'partially_translated', + UNTRANSLATABLE = 'untranslatable', + FAILED = 'failed', +} + +export interface FilterOptions { + status?: StatusFilter; + author?: AuthorFilter; +} diff --git a/x-pack/solutions/security/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx index 83019347d309f..1cc1e49516364 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx @@ -81,7 +81,7 @@ jest.mock('../../common/lib/kibana', () => ({ services: { application: { capabilities: { - siem: { + siemV2: { crud: true, }, }, diff --git a/x-pack/solutions/security/plugins/security_solution/public/threat_intelligence/links.ts b/x-pack/solutions/security/plugins/security_solution/public/threat_intelligence/links.ts index afcb386981330..b9bb2c32d480a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/threat_intelligence/links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/threat_intelligence/links.ts @@ -7,7 +7,7 @@ import { getSecuritySolutionLink } from '@kbn/threat-intelligence-plugin/public'; import type { SecurityPageName } from '../../common/constants'; -import { SERVER_APP_ID } from '../../common/constants'; +import { SECURITY_FEATURE_ID } from '../../common/constants'; import type { LinkItem } from '../common/links'; /** @@ -18,5 +18,5 @@ import type { LinkItem } from '../common/links'; export const indicatorsLinks: LinkItem = { ...getSecuritySolutionLink('indicators'), globalNavPosition: 8, - capabilities: [`${SERVER_APP_ID}.threat-intelligence`], + capabilities: [`${SECURITY_FEATURE_ID}.threat-intelligence`], }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/threat_intelligence/routes.tsx b/x-pack/solutions/security/plugins/security_solution/public/threat_intelligence/routes.tsx index edb57a635222a..16c473bbd83d1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/threat_intelligence/routes.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/threat_intelligence/routes.tsx @@ -31,11 +31,18 @@ import { deleteOneQuery, setQuery } from '../common/store/inputs/actions'; import { InputsModelId } from '../common/store/inputs/constants'; import { ArtifactFlyout } from '../management/components/artifact_list_page/components/artifact_flyout'; import { SecurityRoutePageWrapper } from '../common/components/security_route_page_wrapper'; +import { extractTimelineCapabilities } from '../common/utils/timeline_capabilities'; const ThreatIntelligence = memo(() => { - const { threatIntelligence, http } = useKibana().services; + const { + threatIntelligence, + http, + application: { capabilities }, + } = useKibana().services; const ThreatIntelligencePlugin = threatIntelligence.getComponent(); + const { read: hasAccessToTimeline } = extractTimelineCapabilities(capabilities); + const sourcererDataView = useSourcererDataView(); const securitySolutionStore = getStore() as Store; @@ -50,6 +57,7 @@ const ThreatIntelligence = memo(() => { licenseService, sourcererDataView: sourcererDataView as unknown as SelectedDataView, getUseInvestigateInTimeline: useInvestigateInTimeline, + hasAccessToTimeline, blockList: { canWriteBlocklist, @@ -85,7 +93,7 @@ const ThreatIntelligence = memo(() => { SiemSearchBar, }), - [canWriteBlocklist, http, securitySolutionStore, sourcererDataView] + [canWriteBlocklist, http, securitySolutionStore, sourcererDataView, hasAccessToTimeline] ); return ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/add_to_favorites/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/add_to_favorites/index.test.tsx index 8aeec715c9941..51bc006c5dea7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/add_to_favorites/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/add_to_favorites/index.test.tsx @@ -10,6 +10,9 @@ import { render } from '@testing-library/react'; import { mockTimelineModel, TestProviders } from '../../../common/mock'; import { AddToFavoritesButton } from '.'; import { TimelineStatusEnum } from '../../../../common/api/timeline'; +import { useUserPrivileges } from '../../../common/components/user_privileges'; + +jest.mock('../../../common/components/user_privileges'); const mockGetState = jest.fn(); jest.mock('react-redux', () => { @@ -38,6 +41,14 @@ const renderAddFavoritesButton = () => ); describe('AddToFavoritesButton', () => { + beforeEach(() => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { + crud: true, + }, + }); + }); + it('should render favorite button enabled and unchecked', () => { mockGetState.mockReturnValue({ ...mockTimelineModel, @@ -54,6 +65,21 @@ describe('AddToFavoritesButton', () => { expect(queryByTestId('timeline-favorite-filled-star')).not.toBeInTheDocument(); }); + it('should render favorite button disabled for users without write access to timeline', () => { + mockGetState.mockReturnValue({ + ...mockTimelineModel, + status: TimelineStatusEnum.active, + }); + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { + crud: false, + }, + }); + + const { getByTestId } = renderAddFavoritesButton(); + expect(getByTestId('timeline-favorite-empty-star')).toHaveProperty('disabled'); + }); + it('should render favorite button disabled for a draft timeline', () => { mockGetState.mockReturnValue({ ...mockTimelineModel, diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/add_to_favorites/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/add_to_favorites/index.tsx index 3acbbce33ee98..a6c372023164d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/add_to_favorites/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/add_to_favorites/index.tsx @@ -13,6 +13,7 @@ import type { State } from '../../../common/store'; import { selectTimelineById } from '../../store/selectors'; import { timelineActions } from '../../store'; import { TimelineStatusEnum } from '../../../../common/api/timeline'; +import { useUserPrivileges } from '../../../common/components/user_privileges'; const ADD_TO_FAVORITES = i18n.translate( 'xpack.securitySolution.timeline.addToFavoriteButtonLabel', @@ -44,8 +45,12 @@ export const AddToFavoritesButton = React.memo(({ tim const { isFavorite, status } = useSelector((state: State) => selectTimelineById(state, timelineId) ); + const { + timelinePrivileges: { crud: canWriteTimeline }, + } = useUserPrivileges(); const isTimelineDraftOrImmutable = status !== TimelineStatusEnum.active; + const isDisabled = !canWriteTimeline || isTimelineDraftOrImmutable; const label = isFavorite ? REMOVE_FROM_FAVORITES : ADD_TO_FAVORITES; const handleClick = useCallback( @@ -57,7 +62,7 @@ export const AddToFavoritesButton = React.memo(({ tim { const origin = jest.requireActual('react-redux'); + const mockDispatch = jest.fn(); return { ...origin, - useDispatch: jest.fn(), + useDispatch: jest.fn(() => mockDispatch), }; }); jest.mock('react-router-dom', () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/modal/actions/save_timeline_button.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/modal/actions/save_timeline_button.test.tsx index 31103f0932d2e..7f1f219e3bc92 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/modal/actions/save_timeline_button.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/modal/actions/save_timeline_button.test.tsx @@ -45,7 +45,7 @@ const renderSaveTimelineButton = () => describe('SaveTimelineButton', () => { it('should render components', async () => { (useUserPrivileges as jest.Mock).mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true }, + timelinePrivileges: { crud: true }, }); mockGetState.mockReturnValue({ ...mockTimelineModel, @@ -65,7 +65,7 @@ describe('SaveTimelineButton', () => { it('should override the default text and color of the button', async () => { (useUserPrivileges as jest.Mock).mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true }, + timelinePrivileges: { crud: true }, }); mockGetState.mockReturnValue({ ...mockTimelineModel, @@ -92,7 +92,7 @@ describe('SaveTimelineButton', () => { it('should open the timeline save modal', async () => { (useUserPrivileges as jest.Mock).mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true }, + timelinePrivileges: { crud: true }, }); mockGetState.mockReturnValue({ ...mockTimelineModel, @@ -113,7 +113,7 @@ describe('SaveTimelineButton', () => { it('should disable the save timeline button when the user does not have write access', () => { (useUserPrivileges as jest.Mock).mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: false }, + timelinePrivileges: { crud: false }, }); mockGetState.mockReturnValue(mockTimelineModel); @@ -124,7 +124,7 @@ describe('SaveTimelineButton', () => { it('should disable the save timeline button when the timeline is immutable', () => { (useUserPrivileges as jest.Mock).mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true }, + timelinePrivileges: { crud: true }, }); mockGetState.mockReturnValue({ ...mockTimelineModel, status: TimelineStatusEnum.immutable }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/modal/actions/save_timeline_button.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/modal/actions/save_timeline_button.tsx index de9d35b283517..9687bbcb82054 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/modal/actions/save_timeline_button.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/modal/actions/save_timeline_button.tsx @@ -55,7 +55,7 @@ export const SaveTimelineButton = React.memo( // TODO: User may have Crud privileges but they may not have access to timeline index. // Do we need to check that? const { - kibanaSecuritySolutionsPrivileges: { crud: canEditTimelinePrivilege }, + timelinePrivileges: { crud: canEditTimelinePrivilege }, } = useUserPrivileges(); const { status, isSaving } = useSelector((state: State) => diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/notes/old_notes.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/notes/old_notes.tsx index 09c45d887b373..a1b77bc5672c1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/notes/old_notes.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/notes/old_notes.tsx @@ -115,7 +115,7 @@ interface NotesTabContentProps { */ export const OldNotes: React.FC = React.memo(({ timelineId }) => { const dispatch = useDispatch(); - const { kibanaSecuritySolutionsPrivileges } = useUserPrivileges(); + const { notesPrivileges } = useUserPrivileges(); const getScrollToTop = useMemo(() => getScrollToTopSelector(), []); const scrollToTop = useShallowEqualSelector((state) => getScrollToTop(state, timelineId)); @@ -182,7 +182,7 @@ export const OldNotes: React.FC = React.memo(({ timelineId - {!isImmutable && kibanaSecuritySolutionsPrivileges.crud === true && ( + {!isImmutable && notesPrivileges.crud === true && ( { it('should render the callout and save components', () => { (useUserPrivileges as jest.Mock).mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true }, + timelinePrivileges: { crud: true }, }); const mockStore = createMockStore({ diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/index.test.tsx index 5a3ba28a82767..4e39ee6ccd6fd 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/index.test.tsx @@ -109,7 +109,8 @@ describe('StatefulOpenTimeline', () => { pageName: SecurityPageName.timelines, }); useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true, read: true }, + timelinePrivileges: { crud: true, read: true }, + notesPrivileges: { crud: true, read: true }, }); mockHistory = []; (useHistory as jest.Mock).mockReturnValue(mockHistory); @@ -804,4 +805,44 @@ describe('StatefulOpenTimeline', () => { expect(queryByTestId('create-rule-from-timeline')).not.toBeInTheDocument(); }); }); + + describe('privileges', () => { + test('installs prepackaged timelines when the user has sufficient privileges', async () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { crud: true }, + }); + mount( + + + + ); + + await waitFor(() => { + expect(mockInstallPrepackagedTimelines).toHaveBeenCalled(); + }); + }); + + test('does not install prepackaged timelines when the user has insufficient privileges', async () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { crud: false }, + }); + mount( + + + + ); + + await waitFor(() => { + expect(mockInstallPrepackagedTimelines).not.toHaveBeenCalled(); + }); + }); + }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/index.tsx index 8af06fe910f99..7cd7cbe18927f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/index.tsx @@ -16,6 +16,7 @@ import { import { useNavigation } from '../../../common/lib/kibana'; import { SecurityPageName } from '../../../../common/constants'; import { useShallowEqualSelector } from '../../../common/hooks/use_selector'; +import { useUserPrivileges } from '../../../common/components/user_privileges'; import type { SortFieldTimeline } from '../../../../common/api/timeline'; import { TimelineId } from '../../../../common/types/timeline'; import type { TimelineModel } from '../../store/model'; @@ -368,13 +369,20 @@ export const StatefulOpenTimelineComponent = React.memo( focusInput(); }, []); + const { + timelinePrivileges: { crud: canWriteTimelines }, + } = useUserPrivileges(); useEffect(() => { const fetchData = async () => { - await installPrepackagedTimelines(); - refetch(); + if (canWriteTimelines) { + await installPrepackagedTimelines(); + refetch(); + } else { + refetch(); + } }; fetchData(); - }, [refetch, installPrepackagedTimelines]); + }, [refetch, installPrepackagedTimelines, canWriteTimelines]); return !isModal ? ( { jest.mock('./hooks/use_delete_note'); +jest.mock('../../../../common/components/user_privileges'); + const deleteMutateMock = jest.fn(); describe('NotePreviews', () => { @@ -51,6 +54,11 @@ describe('NotePreviews', () => { onError: jest.fn(), isLoading: false, }); + (useUserPrivileges as jest.Mock).mockReturnValue({ + notesPrivileges: { + crud: true, + }, + }); }); test('it renders a note preview for each note when isModal is false', () => { @@ -341,4 +349,37 @@ describe('NotePreviews', () => { expect(deleteMutateMock.mock.calls[0][0]).toBe('test-id-1'); }); }); + + describe('Insuffiecient privileges', () => { + it('should not show the delete note button', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + notesPrivileges: { + crud: false, + }, + }); + + const timeline = mockTimelineResults[0]; + (useDeepEqualSelector as jest.Mock).mockReturnValue(timeline); + + const wrapper = mountWithI18nProvider( + , + { + wrappingComponent: createReactQueryWrapper(), + } + ); + + expect(wrapper.find('[data-test-subj="delete-note"]').exists()).toBe(false); + }); + }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/note_previews/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/note_previews/index.tsx index 19f98aff651fa..4080e254303a2 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/note_previews/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/note_previews/index.tsx @@ -35,6 +35,7 @@ import { useSourcererDataView } from '../../../../sourcerer/containers'; import { useDeleteNote } from './hooks/use_delete_note'; import { getTimelineNoteSelector } from '../../timeline/tabs/notes/selectors'; import { DocumentEventTypes } from '../../../../common/lib/telemetry'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; export const NotePreviewsContainer = styled.section` padding-top: ${({ theme }) => `${theme.eui.euiSizeS}`}; @@ -190,21 +191,10 @@ const NoteActions = React.memo<{ savedObjectId, showToggleEventDetailsAction = true, }) => { - return eventId && timelineId ? ( - <> - {showToggleEventDetailsAction ? ( - - ) : null} - - - ) : ( + const { + notesPrivileges: { crud: canCrudNotes }, + } = useUserPrivileges(); + const DeleteButton = canCrudNotes ? ( + ) : null; + + return eventId && timelineId ? ( + <> + {showToggleEventDetailsAction ? ( + + ) : null} + {DeleteButton} + + ) : ( + <>{DeleteButton} ); } ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/open_timeline.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/open_timeline.test.tsx index 713dff571847b..1593e52f931cb 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/open_timeline.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/open_timeline.test.tsx @@ -106,7 +106,7 @@ describe('OpenTimeline', () => { test('it shows the delete action columns when onDeleteSelected and deleteTimelines are specified', () => { useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true, read: true }, + timelinePrivileges: { crud: true, read: true }, }); const defaultProps = getDefaultTestProps(mockResults); const wrapper = mountWithIntl( @@ -190,7 +190,7 @@ describe('OpenTimeline', () => { deleteTimelines: undefined, }; useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: false, read: true }, + timelinePrivileges: { crud: false, read: true }, }); const wrapper = mountWithIntl( @@ -354,7 +354,7 @@ describe('OpenTimeline', () => { test('it should disable delete timeline if no timeline is selected', async () => { useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true, read: true }, + timelinePrivileges: { crud: true, read: true }, }); const defaultProps = { ...getDefaultTestProps(mockResults), @@ -405,7 +405,7 @@ describe('OpenTimeline', () => { test('it should enable delete timeline if a timeline is selected', async () => { useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true, read: true }, + timelinePrivileges: { crud: true, read: true }, }); const defaultProps = { ...getDefaultTestProps(mockResults), @@ -432,7 +432,7 @@ describe('OpenTimeline', () => { test("it should render a selectable timeline table if timelineStatus is active (selecting custom templates' tab)", () => { useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true, read: true }, + timelinePrivileges: { crud: true, read: true }, }); const defaultProps = { ...getDefaultTestProps(mockResults), @@ -451,7 +451,7 @@ describe('OpenTimeline', () => { test('it should include createRule in timeline actions if onCreateRule is passed', () => { useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true, read: true }, + timelinePrivileges: { crud: true, read: true }, }); const defaultProps = { ...getDefaultTestProps(mockResults), @@ -474,7 +474,7 @@ describe('OpenTimeline', () => { timelineStatus: TimelineStatusEnum.active, }; useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: false, read: true }, + timelinePrivileges: { crud: false, read: true }, }); const wrapper = mountWithIntl( @@ -517,7 +517,7 @@ describe('OpenTimeline', () => { test("it should not render a selectable timeline table if timelineStatus is immutable (selecting Elastic templates' tab)", () => { useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true, read: true }, + timelinePrivileges: { crud: true, read: true }, }); const defaultProps = { ...getDefaultTestProps(mockResults), @@ -564,7 +564,7 @@ describe('OpenTimeline', () => { test("it should render a selectable timeline table if timelineStatus is null (no template timelines' tab selected)", () => { useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true, read: true }, + timelinePrivileges: { crud: true, read: true }, }); const defaultProps = { ...getDefaultTestProps(mockResults), @@ -587,7 +587,7 @@ describe('OpenTimeline', () => { timelineStatus: null, }; useUserPrivilegesMock.mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: false, read: true }, + timelinePrivileges: { crud: false, read: true }, }); const wrapper = mountWithIntl( diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/open_timeline.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/open_timeline.tsx index 5a1a9155bb5c1..3c62ebbcf065d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/open_timeline.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/open_timeline.tsx @@ -78,9 +78,9 @@ export const OpenTimeline = React.memo( onCompleteEditTimelineAction, } = useEditTimelineActions(); const tableRef = useRef | null>(null); - const { kibanaSecuritySolutionsPrivileges } = useUserPrivileges(); + const { timelinePrivileges } = useUserPrivileges(); const { getBatchItemsPopoverContent } = useEditTimelineBatchActions({ - deleteTimelines: kibanaSecuritySolutionsPrivileges.crud ? deleteTimelines : undefined, + deleteTimelines: timelinePrivileges.crud ? deleteTimelines : undefined, selectedItems, tableRef, timelineType, @@ -156,7 +156,7 @@ export const OpenTimeline = React.memo( }, [setImportDataModalToggle, refetch]); const actionTimelineToShow = useMemo(() => { - if (kibanaSecuritySolutionsPrivileges.crud) { + if (timelinePrivileges.crud) { const createRule: ActionTimelineToShow[] = ['createRule']; const createRuleFromEql: ActionTimelineToShow[] = ['createRuleFromEql']; const timelineActions: ActionTimelineToShow[] = [ @@ -192,7 +192,7 @@ export const OpenTimeline = React.memo( timelineStatus, onDeleteSelected, deleteTimelines, - kibanaSecuritySolutionsPrivileges, + timelinePrivileges, ]); const SearchRowContent = useMemo(() => <>{templateTimelineFilter}, [templateTimelineFilter]); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/open_timeline_modal/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/open_timeline_modal/index.test.tsx index 00cec44b290be..1496d44a43b2e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/open_timeline_modal/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/open_timeline_modal/index.test.tsx @@ -14,6 +14,7 @@ import { mockOpenTimelineQueryResults } from '../../../../common/mock/timeline_r import { useGetAllTimeline, getAllTimeline } from '../../../containers/all'; import { useTimelineStatus } from '../use_timeline_status'; import { OpenTimelineModal } from '.'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; jest.mock('../../../../common/lib/kibana', () => { const actual = jest.requireActual('../../../../common/lib/kibana'); @@ -53,6 +54,8 @@ jest.mock( children({ width: 100, height: 500 }) ); +jest.mock('../../../../common/components/user_privileges'); + describe('OpenTimelineModal', () => { const mockInstallPrepackagedTimelines = jest.fn(); beforeEach(() => { @@ -68,6 +71,9 @@ describe('OpenTimelineModal', () => { templateTimelineFilter:
, installPrepackagedTimelines: mockInstallPrepackagedTimelines, }); + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { crud: true }, + }); }); afterEach(() => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/index.tsx index 0df2170b0697e..c8fd42d68c435 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/index.tsx @@ -180,7 +180,7 @@ export const TimelinesTable = React.memo( onSelectionChange, }; }, [onSelectionChange]); - const { kibanaSecuritySolutionsPrivileges } = useUserPrivileges(); + const { timelinePrivileges } = useUserPrivileges(); const columns = useMemo( () => getTimelinesTableColumns({ @@ -196,7 +196,7 @@ export const TimelinesTable = React.memo( onToggleShowNotes, showExtendedColumns, timelineType, - hasCrudAccess: kibanaSecuritySolutionsPrivileges.crud, + hasCrudAccess: timelinePrivileges.crud, }), [ actionTimelineToShow, @@ -211,7 +211,7 @@ export const TimelinesTable = React.memo( onToggleShowNotes, showExtendedColumns, timelineType, - kibanaSecuritySolutionsPrivileges, + timelinePrivileges, ] ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.tsx index e6ad5ad0e1f11..ff7e0d0e734a7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.tsx @@ -88,12 +88,7 @@ export const useTimelineTypes = ({ const onFilterClicked = useCallback( (tabId: TimelineType, tabStyle: TimelineTabsStyle) => { - setTimelineTypes((prevTimelineTypes) => { - if (prevTimelineTypes !== tabId) { - setTimelineTypes(tabId); - } - return prevTimelineTypes; - }); + setTimelineTypes(tabId); }, [setTimelineTypes] ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/save_status/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/save_status/index.tsx index 606f674fcd595..5c6b1c606ae70 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/save_status/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/save_status/index.tsx @@ -43,17 +43,23 @@ export const TimelineSaveStatus = React.memo(({ timelin changed = false, status, updated, + show, } = useDeepEqualSelector((state) => - pick(['changed', 'status', 'updated'], getTimeline(state, timelineId) ?? timelineDefaults) + pick( + ['changed', 'status', 'updated', 'show'], + getTimeline(state, timelineId) ?? timelineDefaults + ) ); const isDraft = status === TimelineStatusEnum.draft; + const badgeColor = useMemo(() => (show ? 'warning' : 'default'), [show]); + let statusContent: React.ReactNode; if (isDraft || !updated) { - statusContent = {UNSAVED}; + statusContent = {UNSAVED}; } else if (changed) { - statusContent = {UNSAVED_CHANGES}; + statusContent = {UNSAVED_CHANGES}; } if (!statusContent) return null; diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/helpers.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/helpers.tsx index caf864d4b189b..4c2982b5db9b7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/helpers.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/helpers.tsx @@ -111,11 +111,12 @@ export const isEvenEqlSequence = (event: Ecs): boolean => { }; /** Return eventType raw or signal or eql */ export const getEventType = (event: Ecs): Omit => { - if (!isEmpty(event?.kibana?.alert?.rule?.uuid)) { - return 'signal'; - } else if (!isEmpty(event?.eql?.parentId)) { + if (!isEmpty(event?.eql?.parentId)) { return 'eql'; + } else if (!isEmpty(event?.kibana?.alert?.rule?.uuid)) { + return 'signal'; } + return 'raw'; }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx index 299bb736ec4f2..379bf6c544fe3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx @@ -13,9 +13,11 @@ import { isEmpty, isNumber } from 'lodash/fp'; import React from 'react'; import { css } from '@emotion/css'; import type { FieldSpec } from '@kbn/data-plugin/common'; +import { EntityTypeToIdentifierField } from '../../../../../../common/entity_analytics/types'; import { getAgentTypeForAgentIdField } from '../../../../../common/lib/endpoint/utils/get_agent_type_for_agent_id_field'; import { ALERT_HOST_CRITICALITY, + ALERT_SERVICE_CRITICALITY, ALERT_USER_CRITICALITY, } from '../../../../../../common/field_maps/field_names'; import { AgentStatus } from '../../../../../common/components/endpoint/agents/agent_status'; @@ -35,20 +37,19 @@ import { EVENT_MODULE_FIELD_NAME, EVENT_URL_FIELD_NAME, GEO_FIELD_TYPE, - HOST_NAME_FIELD_NAME, IP_FIELD_TYPE, MESSAGE_FIELD_NAME, REFERENCE_URL_FIELD_NAME, RULE_REFERENCE_FIELD_NAME, SIGNAL_RULE_NAME_FIELD_NAME, SIGNAL_STATUS_FIELD_NAME, - USER_NAME_FIELD_NAME, } from './constants'; import { renderEventModule, RenderRuleName, renderUrl } from './formatted_field_helpers'; import { RuleStatus } from './rule_status'; import { HostName } from './host_name'; import { UserName } from './user_name'; import { AssetCriticalityLevel } from './asset_criticality_level'; +import { ServiceName } from './service_name'; // simple black-list to prevent dragging and dropping fields such as message name const columnNamesNotDraggable = [MESSAGE_FIELD_NAME]; @@ -177,7 +178,7 @@ const FormattedFieldValueComponent: React.FC<{ value={`${value}`} /> ); - } else if (fieldName === HOST_NAME_FIELD_NAME) { + } else if (fieldName === EntityTypeToIdentifierField.host) { return ( ); - } else if (fieldName === USER_NAME_FIELD_NAME) { + } else if (fieldName === EntityTypeToIdentifierField.user) { return ( ); + } else if (fieldName === EntityTypeToIdentifierField.service) { + return ( + + ); } else if (fieldFormat === BYTES_FORMAT) { return ( ); - } else if (fieldName === ALERT_HOST_CRITICALITY || fieldName === ALERT_USER_CRITICALITY) { + } else if ( + fieldName === ALERT_HOST_CRITICALITY || + fieldName === ALERT_USER_CRITICALITY || + fieldName === ALERT_SERVICE_CRITICALITY + ) { return ( void; + value: string | number | undefined | null; + title?: string; +} + +const ServiceNameComponent: React.FC = ({ + fieldName, + Component, + contextId, + eventId, + fieldType, + isAggregatable, + isDraggable, + isButton, + onClick, + title, + value, +}) => { + const eventContext = useContext(StatefulEventContext); + const serviceName = `${value}`; + const isInTimelineContext = serviceName && eventContext?.timelineID; + const { openFlyout } = useExpandableFlyoutApi(); + + const isInSecurityApp = useIsInSecurityApp(); + + const openServiceDetailsSidePanel = useCallback( + (e: React.SyntheticEvent) => { + e.preventDefault(); + + if (onClick) { + onClick(); + } + + if (!eventContext || !isInTimelineContext) { + return; + } + + const { timelineID } = eventContext; + + openFlyout({ + right: { + id: ServicePanelKey, + params: { + serviceName, + contextID: contextId, + scopeId: timelineID, + isDraggable, + }, + }, + }); + }, + [contextId, eventContext, isDraggable, isInTimelineContext, onClick, openFlyout, serviceName] + ); + + const content = useMemo( + () => ( + + + {serviceName} + + + ), + [ + serviceName, + isButton, + isInTimelineContext, + openServiceDetailsSidePanel, + Component, + title, + isInSecurityApp, + ] + ); + + return isString(value) && serviceName.length > 0 ? ( + isDraggable ? ( + + {content} + + ) : ( + content + ) + ) : ( + getEmptyTagValue() + ); +}; + +export const ServiceName = React.memo(ServiceNameComponent); +ServiceName.displayName = 'ServiceName'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/properties/notes_flyout.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/properties/notes_flyout.tsx index 8ff78376c7683..8621faa650d48 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/properties/notes_flyout.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/properties/notes_flyout.tsx @@ -19,6 +19,7 @@ import type { EuiTheme } from '@kbn/react-kibana-context-styled'; import type { NoteCardsProps } from '../../notes/note_cards'; import { NoteCards } from '../../notes/note_cards'; import * as i18n from './translations'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; export type NotesFlyoutProps = { show: boolean; @@ -46,6 +47,9 @@ const NotesFlyoutContainer = styled(EuiFlyoutResizable)` export const NotesFlyout = React.memo(function NotesFlyout(props: NotesFlyoutProps) { const { eventId, toggleShowAddNote, show, onClose, associateNote, notes, timelineId, onCancel } = props; + const { + notesPrivileges: { crud: showAddNote }, + } = useUserPrivileges(); const notesFlyoutTitleId = useGeneratedHtmlId({ prefix: 'notesFlyoutTitle', @@ -78,7 +82,7 @@ export const NotesFlyout = React.memo(function NotesFlyout(props: NotesFlyoutPro className="notes-in-flyout" data-test-subj="note-cards" notes={notes} - showAddNote={true} + showAddNote={showAddNote} toggleShowAddNote={toggleShowAddNote} eventId={eventId} timelineId={timelineId} diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/eql/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/eql/index.test.tsx index a80a34596b1de..b307e06331039 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/eql/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/eql/index.test.tsx @@ -29,6 +29,8 @@ import { DefaultCellRenderer } from '../../cell_rendering/default_cell_renderer' import { defaultRowRenderers } from '../../body/renderers'; import { useDispatch } from 'react-redux'; import { TimelineTabs } from '@kbn/securitysolution-data-table'; +import { useUserPrivileges } from '../../../../../common/components/user_privileges'; +import { initialUserPrivilegesState } from '../../../../../common/components/user_privileges/user_privileges_context'; const SPECIAL_TEST_TIMEOUT = 30000; @@ -56,6 +58,8 @@ mockUseResizeObserver.mockImplementation(() => ({})); jest.mock('../../../../../common/lib/kibana'); +jest.mock('../../../../../common/components/user_privileges'); + let useTimelineEventsMock = jest.fn(); const loadPageMock = jest.fn(); @@ -125,6 +129,11 @@ describe('EQL Tab', () => { } ); + (useUserPrivileges as jest.Mock).mockReturnValue({ + ...initialUserPrivilegesState(), + notesPrivileges: { read: true }, + }); + HTMLElement.prototype.getBoundingClientRect = jest.fn(() => { return { width: 1000, diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/esql/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/esql/index.tsx index 4f78509c054d1..9e7386c5a7560 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/esql/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/esql/index.tsx @@ -28,6 +28,7 @@ import { useSetDiscoverCustomizationCallbacks } from './customizations/use_set_d import { EmbeddedDiscoverContainer, TimelineESQLGlobalStyles } from './styles'; import { timelineSelectors } from '../../../../store'; import { useShallowEqualSelector } from '../../../../../common/hooks/use_selector'; +import { useUserPrivileges } from '../../../../../common/components/user_privileges'; import { timelineDefaults } from '../../../../store/defaults'; import { savedSearchComparator } from './utils'; import { GET_TIMELINE_DISCOVER_SAVED_SEARCH_TITLE } from './translations'; @@ -52,6 +53,9 @@ export const DiscoverTabContent: FC = ({ timelineId }) savedSearch: savedSearchService, }, } = useKibana(); + const { + timelinePrivileges: { crud: canSaveTimeline }, + } = useUserPrivileges(); const dispatch = useDispatch(); @@ -119,7 +123,6 @@ export const DiscoverTabContent: FC = ({ timelineId }) ]); const combinedDiscoverSavedSearchStateRef = useRef(); - useEffect(() => { if (isFetching) return; if (savedSearchByIdStatus === 'error' && savedSearchId) { @@ -137,6 +140,7 @@ export const DiscoverTabContent: FC = ({ timelineId }) if (!index) return; if (!latestState || combinedDiscoverSavedSearchStateRef.current === latestState) return; if (isEqualWith(latestState, savedSearchById, savedSearchComparator)) return; + if (!canSaveTimeline) return; updateSavedSearch(latestState, timelineId, function onUpdate() { combinedDiscoverSavedSearchStateRef.current = latestState; }); @@ -153,6 +157,7 @@ export const DiscoverTabContent: FC = ({ timelineId }) dispatch, savedSearchId, savedSearchByIdStatus, + canSaveTimeline, ]); useEffect(() => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/index.test.tsx index cc6d70ef1d46b..16b6675536fcd 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/index.test.tsx @@ -16,8 +16,10 @@ import { TimelineTypeEnum } from '../../../../../common/api/timeline'; import { useEsqlAvailability } from '../../../../common/hooks/esql/use_esql_availability'; import { render, screen, waitFor } from '@testing-library/react'; import { useLicense } from '../../../../common/hooks/use_license'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; jest.mock('../../../../common/hooks/use_license'); +jest.mock('../../../../common/components/user_privileges'); const mockUseUiSetting = jest.fn().mockReturnValue([false]); jest.mock('@kbn/kibana-react-plugin/public', () => { @@ -137,4 +139,36 @@ describe('Timeline', () => { expect(screen.queryByTestId(sessionViewTabSubj)).not.toBeInTheDocument(); }); }); + + describe('privileges', () => { + it('should show notes and pinned tabs for users with the required privileges', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { read: true }, + notesPrivileges: { read: true }, + }); + + render( + + + + ); + expect(screen.getByTestId('timelineTabs-notes')).not.toBeDisabled(); + expect(screen.getByTestId('timelineTabs-pinned')).not.toBeDisabled(); + }); + + it('should not show notes and pinned tabs for users with the insufficient privileges', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { read: false }, + notesPrivileges: { read: false }, + }); + + render( + + + + ); + expect(screen.getByTestId('timelineTabs-notes')).toBeDisabled(); + expect(screen.getByTestId('timelineTabs-pinned')).toBeDisabled(); + }); + }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/index.tsx index 86999ff529fa1..88b134cf00e30 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/index.tsx @@ -44,6 +44,7 @@ import { initializeTimelineSettings } from '../../../store/actions'; import { selectTimelineById, selectTimelineESQLSavedSearchId } from '../../../store/selectors'; import { fetchNotesBySavedObjectIds, selectSortedNotesBySavedObjectId } from '../../../../notes'; import { ENABLE_VISUALIZATIONS_IN_FLYOUT_SETTING } from '../../../../../common/constants'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; const HideShowContainer = styled.div.attrs<{ $isVisible: boolean; isOverflowYScroll: boolean }>( ({ $isVisible = false, isOverflowYScroll = false }) => ({ @@ -297,6 +298,11 @@ const TabsContentComponent: React.FC = ({ [timelineSavedObjectId] ); + const { + notesPrivileges: { read: canSeeNotes }, + timelinePrivileges: { read: canSeePinnedTab }, + } = useUserPrivileges(); + // new note system const fetchNotes = useCallback( () => dispatch(fetchNotesBySavedObjectIds({ savedObjectIds: [timelineSavedObjectId] })), @@ -433,7 +439,7 @@ const TabsContentComponent: React.FC = ({ data-test-subj={`timelineTabs-${TimelineTabs.notes}`} onClick={setNotesAsActiveTab} isSelected={activeTab === TimelineTabs.notes} - disabled={timelineType === TimelineTypeEnum.template} + disabled={!canSeeNotes || timelineType === TimelineTypeEnum.template} key={TimelineTabs.notes} > {i18n.NOTES_TAB} @@ -444,7 +450,7 @@ const TabsContentComponent: React.FC = ({ diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/notes/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/notes/index.test.tsx index 452dc1620b946..d6aaa6ba6df9b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/notes/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/notes/index.test.tsx @@ -72,7 +72,8 @@ describe('NotesTabContentComponent', () => { jest.clearAllMocks(); (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(false); (useUserPrivileges as jest.Mock).mockReturnValue({ - kibanaSecuritySolutionsPrivileges: { crud: true }, + notesPrivileges: { crud: true }, + timelinePrivileges: { crud: true }, }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/notes/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/notes/index.tsx index 58522d32dd55f..1ce8570ce1a34 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/notes/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/notes/index.tsx @@ -83,8 +83,8 @@ const NotesTabContentComponent: React.FC = React.memo(({ t const { addError: addErrorToast } = useAppToasts(); const dispatch = useDispatch(); - const { kibanaSecuritySolutionsPrivileges } = useUserPrivileges(); - const canCreateNotes = kibanaSecuritySolutionsPrivileges.crud; + const { notesPrivileges } = useUserPrivileges(); + const canCreateNotes = notesPrivileges.crud; const securitySolutionNotesDisabled = useIsExperimentalFeatureEnabled( 'securitySolutionNotesDisabled' diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/query/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/query/index.test.tsx index caf893e4d0951..746b3b1ceb1dd 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/query/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/query/index.test.tsx @@ -248,6 +248,8 @@ describe('query tab with unified timeline', () => { ); (useUserPrivileges as jest.Mock).mockReturnValue({ + notesPrivileges: { crud: true, read: true }, + timelinePrivileges: { crud: true, read: true }, kibanaSecuritySolutionsPrivileges: { crud: true, read: true }, endpointPrivileges: getEndpointPrivilegesInitialStateMock(), detectionEnginePrivileges: { loading: false, error: undefined, result: undefined }, @@ -555,8 +557,9 @@ describe('query tab with unified timeline', () => { }); const messageColumnIndex = - customColumnOrder.findIndex((header) => header.id === 'message') + 3; - // 3 is the offset for additional leading columns on left + customColumnOrder.findIndex((header) => header.id === 'message') + + // offset for additional leading columns on left + 4; expect(container.querySelector('[data-gridcell-column-id="message"]')).toHaveAttribute( 'data-gridcell-column-index', diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/session/use_session_view.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/session/use_session_view.test.tsx index 54155a493da64..4f346d68739a6 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/session/use_session_view.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/session/use_session_view.test.tsx @@ -43,7 +43,7 @@ jest.mock('../../../../../common/lib/kibana', () => { navigateToApp: jest.fn(), getUrlForApp: jest.fn(), capabilities: { - siem: { crud_alerts: true, read_alerts: true }, + siemV2: { crud_alerts: true, read_alerts: true }, }, }, sessionView: { diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/shared/use_timeline_control_columns.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/shared/use_timeline_control_columns.test.tsx index 7dc3ddc88caae..1830619e77b66 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/shared/use_timeline_control_columns.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/shared/use_timeline_control_columns.test.tsx @@ -5,12 +5,17 @@ * 2.0. */ -import type { EuiDataGridControlColumn } from '@elastic/eui'; -import { TestProviders } from '../../../../../common/mock'; -import { renderHook } from '@testing-library/react'; +import React from 'react'; +import type { EuiDataGridControlColumn, EuiDataGridCellValueElementProps } from '@elastic/eui'; +import { render, renderHook, screen } from '@testing-library/react'; +import { TestProviders, mockTimelineData } from '../../../../../common/mock'; import { useLicense } from '../../../../../common/hooks/use_license'; import { useTimelineControlColumn } from './use_timeline_control_columns'; import { TimelineId } from '@kbn/timelines-plugin/public/store/timeline'; +import type { UnifiedTimelineDataGridCellContext } from '../../types'; +import { useUserPrivileges } from '../../../../../common/components/user_privileges'; +import { initialUserPrivilegesState } from '../../../../../common/components/user_privileges/user_privileges_context'; +import { useTimelineUnifiedDataTableContext } from '../../unified_components/data_table/use_timeline_unified_data_table_context'; jest.mock('../../../../../common/hooks/use_license', () => ({ useLicense: jest.fn().mockReturnValue({ @@ -18,6 +23,9 @@ jest.mock('../../../../../common/hooks/use_license', () => ({ }), })); +jest.mock('../../unified_components/data_table/use_timeline_unified_data_table_context'); +jest.mock('../../../../../common/components/user_privileges'); + const useLicenseMock = useLicense as jest.Mock; describe('useTimelineControlColumns', () => { @@ -84,4 +92,115 @@ describe('useTimelineControlColumns', () => { expect(controlColumn.width).toBe(152); }); }); + + describe('privileges', () => { + const defaultProps = { + ariaRowindex: 2, + checked: false, + columnId: '', + columnValues: 'abc def', + disableExpandAction: false, + data: mockTimelineData[0].data, + ecsData: mockTimelineData[0].ecs, + eventId: 'abc', + eventIdToNoteIds: {}, + index: 2, + isEventPinned: false, + loadingEventIds: [], + onEventDetailsPanelOpened: () => {}, + onRowSelected: () => {}, + refetch: () => {}, + rowIndex: 10, + setEventsDeleted: () => {}, + setEventsLoading: () => {}, + showCheckboxes: true, + timelineId: 'test', + toggleShowNotes: () => {}, + setCellProps: () => {}, + isExpandable: true, + isExpanded: false, + isDetails: true, + colIndex: 0, + }; + + type RowCellRendererComponent = ( + props: EuiDataGridCellValueElementProps & UnifiedTimelineDataGridCellContext + ) => React.JSX.Element; + + beforeEach(() => { + useLicenseMock.mockReturnValue({ + isEnterprise: () => true, + isPlatinumPlus: () => true, + }); + (useTimelineUnifiedDataTableContext as jest.Mock).mockReturnValue({ + expanded: { id: mockTimelineData[0]._id }, + }); + }); + + it('should render the notes and pin buttons when the user has the correct privileges', async () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + ...initialUserPrivilegesState(), + notesPrivileges: { crud: true, read: true }, + timelinePrivileges: { crud: true }, + }); + + const { result } = renderHook( + () => + useTimelineControlColumn({ + timelineId: TimelineId.test, + refetch: refetchMock, + events: mockTimelineData, + pinnedEventIds: {}, + eventIdToNoteIds: {}, + onToggleShowNotes: jest.fn(), + }), + { + wrapper: TestProviders, + } + ); + const ControlColumnActions = result.current[0].rowCellRender as RowCellRendererComponent; + + render( + + + + ); + + expect(await screen.findByTestId('timeline-notes-button-small')).toBeVisible(); + expect(await screen.findByTestId('pin')).toBeVisible(); + }); + + it('should not render the notes and pin buttons when the user does not have the correct privilege', async () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + ...initialUserPrivilegesState(), + notesPrivileges: { crud: false, read: false }, + timelinePrivileges: { crud: false }, + }); + + const { result } = renderHook( + () => + useTimelineControlColumn({ + timelineId: TimelineId.test, + refetch: refetchMock, + events: mockTimelineData, + pinnedEventIds: {}, + eventIdToNoteIds: {}, + onToggleShowNotes: jest.fn(), + }), + { + wrapper: TestProviders, + } + ); + const ControlColumnActions = result.current[0].rowCellRender as RowCellRendererComponent; + + render( + + + + ); + + expect(await screen.queryByTestId('timeline-notes-button-small')).not.toBeInTheDocument(); + expect(await screen.queryByTestId('pin')).not.toBeInTheDocument(); + }); + }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/shared/use_timeline_control_columns.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/shared/use_timeline_control_columns.tsx index 979282cd7b752..fa5492b926690 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/shared/use_timeline_control_columns.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/shared/use_timeline_control_columns.tsx @@ -14,6 +14,7 @@ import { getDefaultControlColumn } from '../../body/control_columns'; import { TimelineControlColumnCellRender } from '../../unified_components/data_table/control_column_cell_render'; import type { UnifiedTimelineDataGridCellContext } from '../../types'; import { useTimelineUnifiedDataTableContext } from '../../unified_components/data_table/use_timeline_unified_data_table_context'; +import { useUserPrivileges } from '../../../../../common/components/user_privileges'; interface UseTimelineControlColumnArgs { timelineId: string; @@ -37,6 +38,10 @@ export const useTimelineControlColumn = ({ }: UseTimelineControlColumnArgs) => { const isEnterprisePlus = useLicense().isEnterprise(); const ACTION_BUTTON_COUNT = useMemo(() => (isEnterprisePlus ? 5 : 4), [isEnterprisePlus]); + const { + notesPrivileges: { read: canReadNotes }, + timelinePrivileges: { crud: canWriteTimelines }, + } = useUserPrivileges(); const RowCellRender = useMemo( () => @@ -84,10 +89,21 @@ export const useTimelineControlColumn = ({ pinnedEventIds={pinnedEventIds} eventIdToNoteIds={eventIdToNoteIds} toggleShowNotes={onToggleShowNotes} + showNotes={canReadNotes} + disablePinAction={!canWriteTimelines} /> ); }, - [events, timelineId, refetch, pinnedEventIds, eventIdToNoteIds, onToggleShowNotes] + [ + events, + timelineId, + refetch, + pinnedEventIds, + eventIdToNoteIds, + onToggleShowNotes, + canReadNotes, + canWriteTimelines, + ] ); return useMemo(() => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/control_column_cell_render.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/control_column_cell_render.tsx index ca9a1b0c06d5e..43c37ec518512 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/control_column_cell_render.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/control_column_cell_render.tsx @@ -45,14 +45,14 @@ export const TimelineControlColumnCellRender = memo(function TimelineControlColu onRowSelected={noOp} onRuleChange={noOp} showCheckboxes={false} - showNotes={true} + showNotes={props.showNotes} timelineId={props.timelineId} ariaRowindex={rowIndex} checked={false} loadingEventIds={props.loadingEventIds} toggleShowNotes={props.toggleShowNotes} disableExpandAction - disablePinAction={false} + disablePinAction={props.disablePinAction} /> ); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/get_event_type_row_classname.ts b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/get_event_type_row_classname.ts index b6058af189c9d..97417303145a8 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/get_event_type_row_classname.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/get_event_type_row_classname.ts @@ -11,12 +11,12 @@ import { getEventType, isEvenEqlSequence, isEventBuildingBlockType } from '../.. export const getEventTypeRowClassName = (ecsData: TimelineItem['ecs']) => { const eventType = getEventType(ecsData); const eventTypeClassName = - eventType === 'raw' - ? 'rawEvent' - : eventType === 'eql' + eventType === 'eql' ? isEvenEqlSequence(ecsData) ? 'eqlSequence' : 'eqlNonSequence' + : eventType === 'raw' + ? 'rawEvent' : 'nonRawEvent'; const buildingBlockTypeClassName = isEventBuildingBlockType(ecsData) ? 'buildingBlockType' : ''; diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/get_row_indicator.test.ts b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/get_row_indicator.test.ts new file mode 100644 index 0000000000000..3f7f3fe8ec6f7 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/get_row_indicator.test.ts @@ -0,0 +1,105 @@ +/* + * 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 { DataTableRecord } from '@kbn/discover-utils'; +import { getTimelineRowTypeIndicator } from './get_row_indicator'; +import type { EuiThemeComputed } from '@elastic/eui'; + +const mockEuiTheme = { + colors: { + primary: 'primary', + accent: 'accent', + warning: 'warning', + lightShade: 'lightShade', + }, +} as EuiThemeComputed; + +describe('getTimelineRowTypeIndicator', () => { + describe('Alert', () => { + it('should return correct label and color for EQL Event', () => { + const row = { + flattened: { + 'event.kind': 'signal', + 'eql.parentId': '123', + 'eql.sequenceNumber': '1-3', + }, + } as unknown as DataTableRecord; + const rowIndicator = getTimelineRowTypeIndicator(row, mockEuiTheme); + expect(rowIndicator).toEqual({ + color: 'accent', + label: 'EQL Sequence', + }); + }); + it('should return correct label and color for non-EQL Event', () => { + const row = { + flattened: { + 'event.kind': 'signal', + }, + } as unknown as DataTableRecord; + const rowIndicator = getTimelineRowTypeIndicator(row, mockEuiTheme); + expect(rowIndicator).toEqual({ + color: 'warning', + label: 'Alert', + }); + }); + }); + + describe('Event', () => { + it('should return correct label and color for EQL Event', () => { + const row = { + flattened: { + 'eql.parentId': '123', + 'eql.sequenceNumber': '1-3', + }, + } as unknown as DataTableRecord; + const rowIndicator = getTimelineRowTypeIndicator(row, mockEuiTheme); + expect(rowIndicator).toEqual({ + color: 'accent', + label: 'EQL Sequence', + }); + }); + it('should return correct label and color for non-EQL Event', () => { + const row = { + flattened: {}, + } as unknown as DataTableRecord; + const rowIndicator = getTimelineRowTypeIndicator(row, mockEuiTheme); + expect(rowIndicator).toMatchObject({ + color: 'lightShade', + label: 'Event', + }); + }); + }); + + describe('EQL Event Type', () => { + it('should return correct label and color for Even EQL Sequence', () => { + const row = { + flattened: { + 'eql.parentId': '123', + 'eql.sequenceNumber': '2-4', + }, + } as unknown as DataTableRecord; + const rowIndicator = getTimelineRowTypeIndicator(row, mockEuiTheme); + expect(rowIndicator).toEqual({ + color: 'primary', + label: 'EQL Sequence', + }); + }); + it('should return correct label and color for Non-Even EQL Sequence', () => { + const row = { + flattened: { + 'eql.parentId': '123', + 'eql.sequenceNumber': '1-4', + }, + } as unknown as DataTableRecord; + const rowIndicator = getTimelineRowTypeIndicator(row, mockEuiTheme); + expect(rowIndicator).toEqual({ + color: 'accent', + label: 'EQL Sequence', + }); + }); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/get_row_indicator.ts b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/get_row_indicator.ts new file mode 100644 index 0000000000000..074077597c521 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/get_row_indicator.ts @@ -0,0 +1,49 @@ +/* + * 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 { EuiThemeComputed } from '@elastic/eui'; +import type { DataTableRecord } from '@kbn/discover-utils'; +import { getFieldValue } from '@kbn/discover-utils'; +import type { UnifiedDataTableProps } from '@kbn/unified-data-table'; +import { isEmpty } from 'lodash'; + +export const getTimelineRowTypeIndicator: NonNullable = ( + row: DataTableRecord, + euiTheme: EuiThemeComputed +) => { + const isAlert = getFieldValue(row, 'event.kind') === 'signal'; + + const isEql = + !isEmpty(getFieldValue(row, 'eql.parentId')) && + !isEmpty(getFieldValue(row, 'eql.sequenceNumber')); + + if (isEql) { + const sequenceNumber = ((getFieldValue(row, 'eql.sequenceNumber') as string) ?? '').split( + '-' + )[0]; + + const isEvenSequence = parseInt(sequenceNumber, 10) % 2 === 0; + + return { + /* alternating colors to differentiate consecutive sequences */ + color: isEvenSequence ? euiTheme.colors.primary : euiTheme.colors.accent, + label: 'EQL Sequence', + }; + } + + if (isAlert) { + return { + color: euiTheme.colors.warning, + label: 'Alert', + }; + } + + return { + color: euiTheme.colors.lightShade, + label: 'Event', + }; +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.tsx index 32f373000f78b..35bed4ddd804b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.tsx @@ -49,6 +49,7 @@ import { TimelineEventDetailRow } from './timeline_event_detail_row'; import { CustomTimelineDataGridBody } from './custom_timeline_data_grid_body'; import { TIMELINE_EVENT_DETAIL_ROW_ID } from '../../body/constants'; import { DocumentEventTypes } from '../../../../../common/lib/telemetry/types'; +import { getTimelineRowTypeIndicator } from './get_row_indicator'; export const SAMPLE_SIZE_SETTING = 500; const DataGridMemoized = React.memo(UnifiedDataTable); @@ -423,6 +424,7 @@ export const TimelineDataTableComponent: React.FC = memo( trailingControlColumns={finalTrailControlColumns} externalControlColumns={leadingControlColumns} onUpdatePageIndex={onUpdatePageIndex} + getRowIndicator={getTimelineRowTypeIndicator} /> diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/index.test.tsx index 7d9bde02259a4..872f3c760f38b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/index.test.tsx @@ -233,7 +233,7 @@ describe('unified timeline', () => { }); expect( container.querySelector(`[data-gridcell-column-id="${field.name}"]`) - ).toHaveAttribute('data-gridcell-column-index', '3'); + ).toHaveAttribute('data-gridcell-column-index', '4'); expect( container.querySelector(`[data-gridcell-column-id="${field.name}"]`) @@ -268,7 +268,7 @@ describe('unified timeline', () => { }); expect( container.querySelector(`[data-gridcell-column-id="${field.name}"]`) - ).toHaveAttribute('data-gridcell-column-index', '3'); + ).toHaveAttribute('data-gridcell-column-index', '4'); expect( container.querySelector(`[data-gridcell-column-id="${field.name}"]`) @@ -482,7 +482,7 @@ describe('unified timeline', () => { }); expect( container.querySelector(`[data-gridcell-column-id="${field.name}"]`) - ).toHaveAttribute('data-gridcell-column-index', '3'); + ).toHaveAttribute('data-gridcell-column-index', '4'); expect( container.querySelector(`[data-gridcell-column-id="${field.name}"]`) diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/styles.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/styles.tsx index 49c33774572e5..f4a30bbcc13f8 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/styles.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/unified_components/styles.tsx @@ -74,8 +74,19 @@ export const StyledTimelineUnifiedDataTable = styled.div.attrs(({ className = '' .udtTimeline [data-gridcell-column-id|='select'] { border-right: none; } - .udtTimeline [data-gridcell-column-id|='openDetails'] .euiDataGridRowCell__contentByHeight { - margin-top: 3px; + .udtTimeline [data-gridcell-column-id|='openDetails'] { + /* custom row height based on number of lines */ + .euiDataGridRowCell__content--lineCountHeight, + + /* auto row height */ + .euiDataGridRowCell__content--autoHeight { + margin-top: 9px; + } + + /* single row height */ + .euiDataGridRowCell__content--defaultHeight { + margin-top: 3px; + } } .udtTimeline @@ -90,11 +101,24 @@ export const StyledTimelineUnifiedDataTable = styled.div.attrs(({ className = '' overflow: visible; } - .udtTimeline [data-gridcell-column-id|='select'] .euiDataGridRowCell__contentByHeight { - margin-top: 5px; + .udtTimeline [data-gridcell-column-id|='select'] { + /* custom row height based on number of lines */ + .euiDataGridRowCell__content--lineCountHeight, + + /* auto row height */ + .euiDataGridRowCell__content--autoHeight { + margin-top: 6px; + } + + /* single row height */ + .euiDataGridRowCell__content--defaultHeight { + margin-top: 3px; + } } .udtTimeline + [data-gridcell-column-id|='select'] + .udtTimeline .euiDataGridRow:hover .euiDataGridRowCell--lastColumn.euiDataGridRowCell--controlColumn { ${({ theme }) => `background-color: ${theme.eui.colorLightShade};`}; @@ -120,7 +144,6 @@ export const StyledTimelineUnifiedDataTable = styled.div.attrs(({ className = '' } .udtTimeline .euiDataGridRow:has(.eqlSequence), .udtTimeline .euiDataGridRow.eqlSequence { - .euiDataGridRowCell--firstColumn, .euiDataGridRowCell--controlColumn.euiDataGridRowCell--lastColumn, .udt--customRow { ${({ theme }) => `border-left: 4px solid ${theme.eui.euiColorPrimary}`}; @@ -135,7 +158,6 @@ export const StyledTimelineUnifiedDataTable = styled.div.attrs(({ className = '' } .udtTimeline .euiDataGridRow:has(.eqlNonSequence), .udtTimeline .euiDataGridRow.eqlNonSequence { - .euiDataGridRowCell--firstColumn, .euiDataGridRowCell--controlColumn.euiDataGridRowCell--lastColumn, .udt--customRow { ${({ theme }) => `border-left: 4px solid ${theme.eui.euiColorAccent};`} @@ -150,7 +172,6 @@ export const StyledTimelineUnifiedDataTable = styled.div.attrs(({ className = '' } .udtTimeline .euiDataGridRow:has(.nonRawEvent), .udtTimeline .euiDataGridRow.nonRawEvent { - .euiDataGridRowCell--firstColumn, .euiDataGridRowCell--controlColumn.euiDataGridRowCell--lastColumn, .udt--customRow { ${({ theme }) => `border-left: 4px solid ${theme.eui.euiColorWarning};`} @@ -158,7 +179,6 @@ export const StyledTimelineUnifiedDataTable = styled.div.attrs(({ className = '' } .udtTimeline .euiDataGridRow:has(.rawEvent), .udtTimeline .euiDataGridRow.rawEvent { - .euiDataGridRowCell--firstColumn, .euiDataGridRowCell--controlColumn.euiDataGridRowCell--lastColumn, .udt--customRow { ${({ theme }) => `border-left: 4px solid ${theme.eui.euiColorLightShade};`} diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/containers/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/containers/index.test.tsx index c41e62dc2d1cd..37da5e0f3b01d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/containers/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/containers/index.test.tsx @@ -44,7 +44,17 @@ jest.mock('../../common/lib/kibana', () => ({ addWarning: jest.fn(), remove: jest.fn(), }), - useKibana: jest.fn(), + useKibana: jest.fn().mockReturnValue({ + services: { + application: { + capabilities: { + securitySolutionTimeline: { + crud: true, + }, + }, + }, + }, + }), })); const mockUseRouteSpy: jest.Mock = useRouteSpy as jest.Mock; diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/links.ts b/x-pack/solutions/security/plugins/security_solution/public/timelines/links.ts index 9315417d97646..1953b75829bed 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/links.ts @@ -6,7 +6,12 @@ */ import { i18n } from '@kbn/i18n'; -import { SecurityPageName, SERVER_APP_ID, TIMELINES_PATH } from '../../common/constants'; +import { + SECURITY_FEATURE_ID, + SecurityPageName, + TIMELINE_FEATURE_ID, + TIMELINES_PATH, +} from '../../common/constants'; import { TIMELINES } from '../app/translations'; import type { LinkItem } from '../common/links/types'; @@ -15,7 +20,8 @@ export const links: LinkItem = { title: TIMELINES, path: TIMELINES_PATH, globalNavPosition: 7, - capabilities: [`${SERVER_APP_ID}.show`], + // It only makes sense to show this link when the user is also granted access to security solution + capabilities: [[`${SECURITY_FEATURE_ID}.show`, `${TIMELINE_FEATURE_ID}.read`]], globalSearchKeywords: [ i18n.translate('xpack.securitySolution.appLinks.timelines', { defaultMessage: 'Timelines', @@ -29,6 +35,7 @@ export const links: LinkItem = { }), path: `${TIMELINES_PATH}/template`, sideNavDisabled: true, + capabilities: [[`${SECURITY_FEATURE_ID}.show`, `${TIMELINE_FEATURE_ID}.read`]], }, ], }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/pages/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/pages/index.tsx index 2151a2624aeb4..5e6339bd97655 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/pages/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/pages/index.tsx @@ -20,18 +20,20 @@ import { TIMELINES_PATH } from '../../../common/constants'; const timelinesPagePath = `${TIMELINES_PATH}/:tabName(${TimelineTypeEnum.default}|${TimelineTypeEnum.template})`; const timelinesDefaultPath = `${TIMELINES_PATH}/${TimelineTypeEnum.default}`; -export const Timelines = React.memo(() => ( - - - - - ( - - )} - /> - -)); +export const Timelines = React.memo(() => { + return ( + + + + + ( + + )} + /> + + ); +}); Timelines.displayName = 'Timelines'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/pages/timelines_page.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/pages/timelines_page.test.tsx index ee7dfc19d59f5..ae82e2a381010 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/pages/timelines_page.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/pages/timelines_page.test.tsx @@ -8,9 +8,9 @@ import type { ShallowWrapper } from 'enzyme'; import { shallow } from 'enzyme'; import React from 'react'; -import { useKibana } from '../../common/lib/kibana'; import { TimelinesPage } from './timelines_page'; import { useSourcererDataView } from '../../sourcerer/containers'; +import { useUserPrivileges } from '../../common/components/user_privileges'; jest.mock('react-router-dom', () => { const originalModule = jest.requireActual('react-router-dom'); @@ -24,14 +24,7 @@ jest.mock('react-router-dom', () => { }); jest.mock('../../overview/components/events_by_dataset'); jest.mock('../../sourcerer/containers'); -jest.mock('../../common/lib/kibana', () => { - const originalModule = jest.requireActual('../../common/lib/kibana'); - - return { - ...originalModule, - useKibana: jest.fn(), - }; -}); +jest.mock('../../common/components/user_privileges'); describe('TimelinesPage', () => { let wrapper: ShallowWrapper; @@ -41,7 +34,11 @@ describe('TimelinesPage', () => { indicesExist: false, sourcererDataView: {}, }); - (useKibana as unknown as jest.Mock).mockReturnValue({}); + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { + crud: true, + }, + }); wrapper = shallow(); @@ -55,15 +52,9 @@ describe('TimelinesPage', () => { indicesExist: true, sourcererDataView: {}, }); - (useKibana as unknown as jest.Mock).mockReturnValue({ - services: { - application: { - capabilities: { - siem: { - crud: true, - }, - }, - }, + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { + crud: true, }, }); @@ -74,23 +65,18 @@ describe('TimelinesPage', () => { expect(wrapper.exists('[data-test-subj="stateful-open-timeline"]')).toBeTruthy(); }); - it('should not show import button or modal if user does not have crud authorization', () => { - (useKibana as unknown as jest.Mock).mockReturnValue({ - services: { - application: { - capabilities: { - siem: { - crud: false, - }, - }, - }, + it('should not show import button or modal if user does not have crud privileges but it should show the new timeline button', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + timelinePrivileges: { + crud: false, + read: true, }, }); wrapper = shallow(); expect(wrapper.exists('[data-test-subj="timelines-page-open-import-data"]')).toBeFalsy(); - expect(wrapper.exists('[data-test-subj="timelines-page-new"]')).toBeFalsy(); + expect(wrapper.exists('[data-test-subj="timelines-page-new"]')).toBeTruthy(); expect(wrapper.exists('[data-test-subj="stateful-open-timeline"]')).toBeTruthy(); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/pages/timelines_page.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/pages/timelines_page.tsx index 08cf46b41ad35..d213eeaf8f5f0 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/pages/timelines_page.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/pages/timelines_page.tsx @@ -12,21 +12,22 @@ import { NewTimelineButton } from '../components/new_timeline'; import { TimelineTypeEnum } from '../../../common/api/timeline'; import { HeaderPage } from '../../common/components/header_page'; import { SecuritySolutionPageWrapper } from '../../common/components/page_wrapper'; -import { useKibana } from '../../common/lib/kibana'; -import { SpyRoute } from '../../common/utils/route/spy_routes'; +import { useUserPrivileges } from '../../common/components/user_privileges'; import { StatefulOpenTimeline } from '../components/open_timeline'; import * as i18n from './translations'; import { SecurityPageName } from '../../app/types'; import { useSourcererDataView } from '../../sourcerer/containers'; import { EmptyPrompt } from '../../common/components/empty_prompt'; +import { SecurityRoutePageWrapper } from '../../common/components/security_route_page_wrapper'; export const DEFAULT_SEARCH_RESULTS_PER_PAGE = 10; export const TimelinesPage = React.memo(() => { const { tabName } = useParams<{ pageName: SecurityPageName; tabName: string }>(); const { indicesExist } = useSourcererDataView(); - const capabilitiesCanUserCRUD: boolean = - !!useKibana().services?.application?.capabilities?.siem?.crud; + const { + timelinePrivileges: { crud: canWriteTimeline }, + } = useUserPrivileges(); const [isImportDataModalOpen, setImportDataModal] = useState(false); const openImportModal = useCallback(() => { @@ -37,12 +38,12 @@ export const TimelinesPage = React.memo(() => { tabName === TimelineTypeEnum.default ? TimelineTypeEnum.default : TimelineTypeEnum.template; return ( - <> + {indicesExist ? ( - {capabilitiesCanUserCRUD && ( - + + {canWriteTimeline && ( { {i18n.ALL_TIMELINES_IMPORT_TIMELINE_TITLE} - - - - - )} + )} + + + + + { ) : ( )} - - - + ); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/store/middlewares/create_timeline_middlewares.ts b/x-pack/solutions/security/plugins/security_solution/public/timelines/store/middlewares/create_timeline_middlewares.ts index d473f509c688c..effb4b0819773 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/store/middlewares/create_timeline_middlewares.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/store/middlewares/create_timeline_middlewares.ts @@ -12,9 +12,11 @@ import { favoriteTimelineMiddleware } from './timeline_favorite'; import { addNoteToTimelineMiddleware } from './timeline_note'; import { addPinnedEventToTimelineMiddleware } from './timeline_pinned_event'; import { saveTimelineMiddleware } from './timeline_save'; +import { timelinePrivilegesMiddleware } from './timeline_privileges'; export function createTimelineMiddlewares(kibana: CoreStart) { return [ + timelinePrivilegesMiddleware(kibana), timelineChangedMiddleware, favoriteTimelineMiddleware(kibana), addNoteToTimelineMiddleware(kibana), diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/store/middlewares/timeline_changed.test.ts b/x-pack/solutions/security/plugins/security_solution/public/timelines/store/middlewares/timeline_changed.test.ts index ac8412f2fe8f5..d48715cc6be5b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/store/middlewares/timeline_changed.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/store/middlewares/timeline_changed.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { createMockStore } from '../../../common/mock'; +import { createMockStore, kibanaMock } from '../../../common/mock'; import { selectTimelineById } from '../selectors'; import { TimelineId } from '../../../../common/types/timeline'; @@ -79,10 +79,10 @@ const timelineChangedTypesCopy = [ const setChangedMock = setChanged as unknown as jest.Mock; describe('Timeline changed middleware', () => { - let store = createMockStore(); + let store = createMockStore(undefined, undefined, kibanaMock); beforeEach(() => { - store = createMockStore(); + store = createMockStore(undefined, undefined, kibanaMock); setChangedMock.mockClear(); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/store/middlewares/timeline_privileges.test.ts b/x-pack/solutions/security/plugins/security_solution/public/timelines/store/middlewares/timeline_privileges.test.ts new file mode 100644 index 0000000000000..96589c64104ed --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/store/middlewares/timeline_privileges.test.ts @@ -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 { createMockStore, kibanaMock } from '../../../common/mock'; +import { TimelineId } from '../../../../common/types/timeline'; + +import { showTimeline } from '../actions'; + +jest.mock('../actions', () => { + const actual = jest.requireActual('../actions'); + const showTL = jest.fn((...args) => actual.showTimeline(...args)); + (showTL as unknown as { match: Function }).match = () => false; + (showTL as unknown as { type: string }).type = actual.showTimeline.type; + return { + ...actual, + showTimeline: showTL, + }; +}); + +const showTimelineMock = showTimeline as unknown as jest.Mock; + +describe('Timeline privileges middleware', () => { + let store = createMockStore(undefined, undefined, kibanaMock); + + beforeEach(() => { + store = createMockStore(undefined, undefined, kibanaMock); + showTimelineMock.mockClear(); + }); + + it('should not show a toast when a timeline should be shown to a user with sufficient timeline privileges', async () => { + const addWarningMock = jest.spyOn(kibanaMock.notifications.toasts, 'addWarning'); + + await store.dispatch(showTimeline({ id: TimelineId.test, show: true })); + + expect(addWarningMock).not.toHaveBeenCalled(); + }); + + it('should show a toast when a timeline should be shown to a user with insufficient timeline privileges', async () => { + const addWarningMock = jest.spyOn(kibanaMock.notifications.toasts, 'addWarning'); + store = createMockStore(undefined, undefined, { + ...kibanaMock, + application: { + ...kibanaMock.application, + capabilities: { + ...kibanaMock.application.capabilities, + securitySolutionTimeline: { + read: false, + }, + }, + }, + }); + await store.dispatch(showTimeline({ id: TimelineId.test, show: true })); + + expect(addWarningMock).toHaveBeenCalled(); + expect(showTimelineMock).toHaveBeenCalledWith( + expect.objectContaining({ id: TimelineId.test, show: false }) + ); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/store/middlewares/timeline_privileges.ts b/x-pack/solutions/security/plugins/security_solution/public/timelines/store/middlewares/timeline_privileges.ts new file mode 100644 index 0000000000000..504f64a449f8c --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/store/middlewares/timeline_privileges.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 type { Action, Middleware } from 'redux'; +import type { CoreStart } from '@kbn/core/public'; +import { i18n } from '@kbn/i18n'; + +import type { State } from '../../../common/store/types'; + +import { showTimeline } from '../actions'; +import { extractTimelineCapabilities } from '../../../common/utils/timeline_capabilities'; + +function isShowTimelineAction(action: Action): action is ReturnType { + return action.type === showTimeline.type; +} + +export const timelinePrivilegesMiddleware: (kibana: CoreStart) => Middleware<{}, State> = + (kibana: CoreStart) => (store) => (next) => async (action: Action) => { + const { read: hasAccessToTimeline } = extractTimelineCapabilities( + kibana.application.capabilities + ); + + if (isShowTimelineAction(action) && action.payload.show && !hasAccessToTimeline) { + kibana.notifications.toasts.addWarning({ + title: i18n.translate( + 'xpack.securitySolution.timeline.toast.insufficientPrivileges.title', + { + defaultMessage: 'Insufficient privileges (timeline)', + } + ), + text: i18n.translate('xpack.securitySolution.timeline.toast.insufficientPrivileges.text', { + defaultMessage: + 'You are trying to open a timeline but you do not have sufficient privileges. Please contact your administrator in order to get set up with the correct privileges for timeline.', + }), + }); + return next(showTimeline({ id: action.payload.id, show: false })); + } else { + return next(action); + } + }; diff --git a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/fleet_services.ts b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/fleet_services.ts index b28f72fb95b7d..bfd2b93769fbc 100644 --- a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/fleet_services.ts +++ b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/fleet_services.ts @@ -122,6 +122,7 @@ const getAgentPolicyDataForUpdate = ( 'download_source_id', 'fleet_server_host_id', 'global_data_tags', + 'agentless', 'has_fleet_server', 'id', 'inactivity_timeout', diff --git a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/detections_engineer.ts b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/detections_engineer.ts index 51188f92a46cd..f2e0d5c72001d 100644 --- a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/detections_engineer.ts +++ b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/detections_engineer.ts @@ -17,7 +17,7 @@ export const getDetectionsEngineer: () => Omit = () => { ...noResponseActionsRole.kibana[0], feature: { ...noResponseActionsRole.kibana[0].feature, - siem: [ + siemV2: [ 'minimal_all', 'policy_management_read', @@ -29,6 +29,8 @@ export const getDetectionsEngineer: () => Omit = () => { 'actions_log_management_read', ], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], }, }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/endpoint_operations_analyst.ts b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/endpoint_operations_analyst.ts index 168e88386f2d3..21bf6c7346c16 100644 --- a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/endpoint_operations_analyst.ts +++ b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/endpoint_operations_analyst.ts @@ -57,7 +57,7 @@ export const getEndpointOperationsAnalyst: () => Omit = () => { osquery: ['all'], securitySolutionCasesV2: ['all'], builtinAlerts: ['all'], - siem: [ + siemV2: [ 'all', 'read_alerts', 'policy_management_all', @@ -74,6 +74,8 @@ export const getEndpointOperationsAnalyst: () => Omit = () => { 'scan_operations_all', 'workflow_insights_all', ], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], }, spaces: ['*'], }, diff --git a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/endpoint_security_policy_manager.ts b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/endpoint_security_policy_manager.ts index ed82f4026c1aa..6535f42154a20 100644 --- a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/endpoint_security_policy_manager.ts +++ b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/endpoint_security_policy_manager.ts @@ -17,7 +17,7 @@ export const getEndpointSecurityPolicyManager: () => Omit = () => ...noResponseActionsRole.kibana[0], feature: { ...noResponseActionsRole.kibana[0].feature, - siem: [ + siemV2: [ 'minimal_all', 'policy_management_all', @@ -29,6 +29,8 @@ export const getEndpointSecurityPolicyManager: () => Omit = () => 'workflow_insights_all', ], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], }, }, ], @@ -44,7 +46,9 @@ export const getEndpointSecurityPolicyManagementReadRole: () => Omit Omit = () => { ...noResponseActionsRole.kibana[0], feature: { ...noResponseActionsRole.kibana[0].feature, - siem: [ + siemV2: [ 'minimal_all', 'policy_management_read', @@ -31,6 +31,8 @@ export const getHunter: () => Omit = () => { 'process_operations_all', 'actions_log_management_all', ], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], }, }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/platform_engineer.ts b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/platform_engineer.ts index 397d1da1cf7b7..ff6c9aaa82933 100644 --- a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/platform_engineer.ts +++ b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/platform_engineer.ts @@ -17,7 +17,7 @@ export const getPlatformEngineer: () => Omit = () => { ...noResponseActionsRole.kibana[0], feature: { ...noResponseActionsRole.kibana[0].feature, - siem: [ + siemV2: [ 'minimal_all', 'policy_management_all', @@ -31,6 +31,8 @@ export const getPlatformEngineer: () => Omit = () => { 'workflow_insights_all', ], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], }, }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/rule_author.ts b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/rule_author.ts index 63286dc4e925b..2c32c21a1d521 100644 --- a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/rule_author.ts +++ b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/rule_author.ts @@ -17,7 +17,7 @@ export const getRuleAuthor: () => Omit = () => { ...noResponseActionsRole.kibana[0], feature: { ...noResponseActionsRole.kibana[0].feature, - siem: [ + siemV2: [ 'all', 'read_alerts', 'crud_alerts', @@ -30,6 +30,8 @@ export const getRuleAuthor: () => Omit = () => { 'actions_log_management_read', 'workflow_insights_all', ], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], }, }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/serverless/es_serverless_resources/roles.yml b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/serverless/es_serverless_resources/roles.yml index 3fe0d44073f3f..467a180d289a3 100644 --- a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/serverless/es_serverless_resources/roles.yml +++ b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/serverless/es_serverless_resources/roles.yml @@ -14,7 +14,7 @@ system_indices_superuser: #-------------------------------------------------------------------------------------------------- # # FILE SOURCE AT: -# https://github.com/elastic/project-controller/blob/main/internal/project/security/config/roles.yml +# https://github.com/elastic/elasticsearch-controller/blob/main/helm/values.yaml # # !!!! IMPORTANT !!!! DO NOT MAKE CHANGES TO THIS FILE, UNLESS THOSE CHANGES # HAVE ALSO BEEN MADE TO PROJECT CONTROLLER (path above) @@ -25,19 +25,19 @@ viewer: cluster: [] indices: - names: - - ".siem-signals*" - - ".lists-*" - - ".items-*" + - '.siem-signals*' + - '.lists-*' + - '.items-*' privileges: - - "read" - - "view_index_metadata" + - 'read' + - 'view_index_metadata' allow_restricted_indices: false - names: - - ".alerts*" - - ".preview.alerts*" + - '.alerts*' + - '.preview.alerts*' privileges: - - "read" - - "view_index_metadata" + - 'read' + - 'view_index_metadata' allow_restricted_indices: false - names: - apm-*-transaction* @@ -49,24 +49,26 @@ viewer: - packetbeat-* - winlogbeat-* - metrics-endpoint.metadata_current_* - - ".fleet-agents*" - - ".fleet-actions*" - - "risk-score.risk-score-*" - - ".asset-criticality.asset-criticality-*" - - ".entities.v1.latest.security_*" - - ".ml-anomalies-*" + - '.fleet-agents*' + - '.fleet-actions*' + - 'risk-score.risk-score-*' + - '.asset-criticality.asset-criticality-*' + - '.entities.v1.latest.security_*' + - '.ml-anomalies-*' privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.read - - feature_siem.read_alerts - - feature_siem.endpoint_list_read + - feature_siemV2.read + - feature_siemV2.read_alerts + - feature_siemV2.endpoint_list_read - feature_securitySolutionCases.read - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.read + - feature_securitySolutionNotes.read - feature_actions.read - feature_builtInAlerts.read - feature_osquery.read @@ -76,7 +78,7 @@ viewer: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' run_as: [] # modeled after t3_analyst @@ -84,14 +86,14 @@ editor: cluster: [] indices: - names: - - ".siem-signals*" - - ".lists-*" - - ".items-*" + - '.siem-signals*' + - '.lists-*' + - '.items-*' privileges: - - "read" - - "view_index_metadata" - - "write" - - "maintenance" + - 'read' + - 'view_index_metadata' + - 'write' + - 'maintenance' allow_restricted_indices: false - names: - apm-*-transaction* @@ -106,47 +108,49 @@ editor: - read - write - names: - - ".internal.alerts*" - - ".alerts*" - - ".internal.preview.alerts*" - - ".preview.alerts*" - - "risk-score.risk-score-*" + - '.internal.alerts*' + - '.alerts*' + - '.internal.preview.alerts*' + - '.preview.alerts*' + - 'risk-score.risk-score-*' privileges: - - "read" - - "view_index_metadata" - - "write" - - "maintenance" + - 'read' + - 'view_index_metadata' + - 'write' + - 'maintenance' - names: - - ".asset-criticality.asset-criticality-*" + - '.asset-criticality.asset-criticality-*' - .entities.v1.latest.security_* privileges: - - "read" - - "write" + - 'read' + - 'write' allow_restricted_indices: false - names: - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all - - feature_siem.policy_management_read # Elastic Defend Policy Management - - feature_siem.host_isolation_all - - feature_siem.process_operations_all - - feature_siem.actions_log_management_all # Response actions history - - feature_siem.file_operations_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all + - feature_siemV2.policy_management_read # Elastic Defend Policy Management + - feature_siemV2.host_isolation_all + - feature_siemV2.process_operations_all + - feature_siemV2.actions_log_management_all # Response actions history + - feature_siemV2.file_operations_all - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.read - feature_builtInAlerts.all - feature_osquery.all @@ -156,15 +160,15 @@ editor: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' run_as: [] t1_analyst: cluster: indices: - names: - - ".alerts-security*" - - ".siem-signals-*" + - '.alerts-security*' + - '.siem-signals-*' privileges: - read - write @@ -179,24 +183,26 @@ t1_analyst: - packetbeat-* - winlogbeat-* - metrics-endpoint.metadata_current_* - - ".fleet-agents*" - - ".fleet-actions*" + - '.fleet-agents*' + - '.fleet-actions*' - risk-score.risk-score-* - .asset-criticality.asset-criticality-* - .entities.v1.latest.security_* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.read - - feature_siem.read_alerts - - feature_siem.endpoint_list_read + - feature_siemV2.read + - feature_siemV2.read_alerts + - feature_siemV2.endpoint_list_read - feature_securitySolutionCases.read - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.read + - feature_securitySolutionNotes.read - feature_actions.read - feature_builtInAlerts.read - feature_osquery.read @@ -207,7 +213,7 @@ t1_analyst: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' t2_analyst: cluster: @@ -235,7 +241,7 @@ t2_analyst: - .fleet-actions* - risk-score.risk-score-* - .entities.v1.latest.security_* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read - names: @@ -244,15 +250,17 @@ t2_analyst: - read - write applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.read - - feature_siem.read_alerts - - feature_siem.endpoint_list_read + - feature_siemV2.read + - feature_siemV2.read_alerts + - feature_siemV2.endpoint_list_read - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.read + - feature_securitySolutionNotes.read - feature_actions.read - feature_builtInAlerts.read - feature_osquery.read @@ -263,7 +271,7 @@ t2_analyst: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' t3_analyst: cluster: @@ -300,31 +308,33 @@ t3_analyst: - .fleet-actions* - risk-score.risk-score-* - .entities.v1.latest.security_* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all - - feature_siem.policy_management_read # Elastic Defend Policy Management - - feature_siem.host_isolation_all - - feature_siem.process_operations_all - - feature_siem.actions_log_management_all # Response actions history - - feature_siem.file_operations_all - - feature_siem.scan_operations_all - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all + - feature_siemV2.policy_management_read # Elastic Defend Policy Management + - feature_siemV2.host_isolation_all + - feature_siemV2.process_operations_all + - feature_siemV2.actions_log_management_all # Response actions history + - feature_siemV2.file_operations_all + - feature_siemV2.scan_operations_all + - feature_siemV2.workflow_insights_all - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.read - feature_builtInAlerts.all - feature_osquery.all @@ -334,7 +344,7 @@ t3_analyst: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' threat_intelligence_analyst: cluster: @@ -370,19 +380,21 @@ threat_intelligence_analyst: - .fleet-actions* - risk-score.risk-score-* - .entities.v1.latest.security_* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.all - - feature_siem.endpoint_list_read - - feature_siem.blocklist_all + - feature_siemV2.all + - feature_siemV2.endpoint_list_read + - feature_siemV2.blocklist_all - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.read - feature_builtInAlerts.read - feature_osquery.all @@ -392,7 +404,7 @@ threat_intelligence_analyst: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' rule_author: cluster: @@ -432,27 +444,29 @@ rule_author: - .fleet-actions* - risk-score.risk-score-* - .entities.v1.latest.security_* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.policy_management_all - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_read - - feature_siem.blocklist_all # Elastic Defend Policy Management - - feature_siem.actions_log_management_read - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.policy_management_all + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_read + - feature_siemV2.blocklist_all # Elastic Defend Policy Management + - feature_siemV2.actions_log_management_read + - feature_siemV2.workflow_insights_all - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.read - feature_builtInAlerts.all - feature_osquery.all @@ -462,7 +476,7 @@ rule_author: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' soc_manager: cluster: @@ -502,32 +516,34 @@ soc_manager: - .fleet-actions* - risk-score.risk-score-* - .asset-criticality.asset-criticality-* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.policy_management_all - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all - - feature_siem.host_isolation_all - - feature_siem.process_operations_all - - feature_siem.actions_log_management_all - - feature_siem.file_operations_all - - feature_siem.execute_operations_all - - feature_siem.scan_operations_all - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.policy_management_all + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all + - feature_siemV2.host_isolation_all + - feature_siemV2.process_operations_all + - feature_siemV2.actions_log_management_all + - feature_siemV2.file_operations_all + - feature_siemV2.execute_operations_all + - feature_siemV2.scan_operations_all + - feature_siemV2.workflow_insights_all - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all @@ -538,10 +554,10 @@ soc_manager: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' detections_admin: - cluster: ["manage_index_templates", "manage_transform"] + cluster: ['manage_index_templates', 'manage_transform'] indices: - names: - apm-*-transaction* @@ -566,7 +582,7 @@ detections_admin: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read - names: @@ -580,15 +596,17 @@ detections_admin: - read - write applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.all - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.all - feature_builtInAlerts.all - feature_dev_tools.all @@ -598,7 +616,7 @@ detections_admin: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' platform_engineer: cluster: @@ -629,27 +647,29 @@ platform_engineer: - read - write - names: - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.all - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.policy_management_all - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all # Elastic Defend Policy Management - - feature_siem.actions_log_management_read - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.policy_management_all + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all # Elastic Defend Policy Management + - feature_siemV2.actions_log_management_read + - feature_siemV2.workflow_insights_all - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.all - feature_builtInAlerts.all - feature_fleet.all @@ -662,7 +682,7 @@ platform_engineer: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' endpoint_operations_analyst: cluster: @@ -686,7 +706,7 @@ endpoint_operations_analyst: - .items* - risk-score.risk-score-* - .entities.v1.latest.security_* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read - names: @@ -704,27 +724,29 @@ endpoint_operations_analyst: - read - write applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.policy_management_all - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all - - feature_siem.host_isolation_all - - feature_siem.process_operations_all - - feature_siem.actions_log_management_all # Response History - - feature_siem.file_operations_all - - feature_siem.execute_operations_all # Execute - - feature_siem.scan_operations_all - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.policy_management_all + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all + - feature_siemV2.host_isolation_all + - feature_siemV2.process_operations_all + - feature_siemV2.actions_log_management_all # Response History + - feature_siemV2.file_operations_all + - feature_siemV2.execute_operations_all # Execute + - feature_siemV2.scan_operations_all + - feature_siemV2.workflow_insights_all - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all @@ -736,7 +758,7 @@ endpoint_operations_analyst: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' endpoint_policy_manager: cluster: @@ -758,7 +780,7 @@ endpoint_policy_manager: - winlogbeat-* - risk-score.risk-score-* - .entities.v1.latest.security_* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read - names: @@ -778,22 +800,24 @@ endpoint_policy_manager: - write - manage applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.all - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.policy_management_all - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all # Elastic Defend Policy Management - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.policy_management_all + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all # Elastic Defend Policy Management + - feature_siemV2.workflow_insights_all - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all @@ -805,4 +829,4 @@ endpoint_policy_manager: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' diff --git a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/soc_manager.ts b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/soc_manager.ts index 20cda46c70ef1..65d3327c8d000 100644 --- a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/soc_manager.ts +++ b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/soc_manager.ts @@ -17,7 +17,7 @@ export const getSocManager: () => Omit = () => { ...noResponseActionsRole.kibana[0], feature: { ...noResponseActionsRole.kibana[0].feature, - siem: [ + siemV2: [ 'minimal_all', 'policy_management_all', @@ -33,6 +33,8 @@ export const getSocManager: () => Omit = () => { 'workflow_insights_all', ], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], }, }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/t1_analyst.ts b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/t1_analyst.ts index 4cc67fb69f4ea..5bdb7c3883f26 100644 --- a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/t1_analyst.ts +++ b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/t1_analyst.ts @@ -17,7 +17,9 @@ export const getT1Analyst: () => Omit = () => { ...noResponseActionsRole.kibana[0], feature: { ...noResponseActionsRole.kibana[0].feature, - siem: ['minimal_all'], + siemV2: ['minimal_all'], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], }, }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/t2_analyst.ts b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/t2_analyst.ts index 32d3fac8ac680..d99ceba8014f3 100644 --- a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/t2_analyst.ts +++ b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/t2_analyst.ts @@ -17,7 +17,9 @@ export const getT2Analyst: () => Omit = () => { ...noResponseActionsRole.kibana[0], feature: { ...noResponseActionsRole.kibana[0].feature, - siem: ['minimal_all', 'actions_log_management_read'], + siemV2: ['minimal_all', 'actions_log_management_read'], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], }, }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/t3_analyst.ts b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/t3_analyst.ts index 2ed145886eac8..b174994e04874 100644 --- a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/t3_analyst.ts +++ b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/t3_analyst.ts @@ -17,7 +17,7 @@ export const getT3Analyst: () => Omit = () => { ...noResponseActionsRole.kibana[0], feature: { ...noResponseActionsRole.kibana[0].feature, - siem: [ + siemV2: [ 'all', 'read_alerts', 'crud_alerts', @@ -34,6 +34,8 @@ export const getT3Analyst: () => Omit = () => { 'scan_operations_all', 'workflow_insights_all', ], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], }, }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/threat_intelligence_analyst.ts b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/threat_intelligence_analyst.ts index 884b9412d06d6..3707cbfb61bfd 100644 --- a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/threat_intelligence_analyst.ts +++ b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/threat_intelligence_analyst.ts @@ -17,7 +17,9 @@ export const getThreatIntelligenceAnalyst: () => Omit = () => { ...noResponseActionsRole.kibana[0], feature: { ...noResponseActionsRole.kibana[0].feature, - siem: ['minimal_all', 'blocklist_all', 'actions_log_management_read'], + siemV2: ['minimal_all', 'blocklist_all', 'actions_log_management_read'], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], }, }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/with_artifact_read_privileges_role.ts b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/with_artifact_read_privileges_role.ts index aa09afb0cb74e..5a168de59f5eb 100644 --- a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/with_artifact_read_privileges_role.ts +++ b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/with_artifact_read_privileges_role.ts @@ -17,13 +17,15 @@ export const getWithArtifactReadPrivilegesRole: () => Omit = () => ...noResponseActionsRole.kibana[0], feature: { ...noResponseActionsRole.kibana[0].feature, - siem: [ + siemV2: [ 'minimal_all', 'blocklist_read', 'trusted_applications_read', 'host_isolation_exceptions_read', 'event_filters_read', ], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], }, }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/with_response_actions_role.ts b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/with_response_actions_role.ts index 7108f0181b868..a8a4bb31b2089 100644 --- a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/with_response_actions_role.ts +++ b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/with_response_actions_role.ts @@ -17,8 +17,8 @@ export const getWithResponseActionsRole: () => Omit = () => { ...noResponseActionsRole.kibana[0], feature: { ...noResponseActionsRole.kibana[0].feature, - siem: [ - ...noResponseActionsRole.kibana[0].feature.siem, + siemV2: [ + ...noResponseActionsRole.kibana[0].feature.siemV2, 'file_operations_all', 'execute_operations_all', 'scan_operations_all', @@ -27,6 +27,8 @@ export const getWithResponseActionsRole: () => Omit = () => { 'actions_log_management_all', 'actions_log_management_read', ], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], }, }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/without_response_actions_role.ts b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/without_response_actions_role.ts index d57ca059de994..4e5b7aa28fff0 100644 --- a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/without_response_actions_role.ts +++ b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/without_response_actions_role.ts @@ -42,7 +42,7 @@ export const getNoResponseActionsRole: () => Omit = () => ({ osquery: ['all'], savedObjectsManagement: ['all'], savedObjectsTagging: ['all'], - siem: [ + siemV2: [ 'minimal_all', 'endpoint_list_all', 'endpoint_list_read', @@ -57,6 +57,8 @@ export const getNoResponseActionsRole: () => Omit = () => ({ 'policy_management_all', 'policy_management_read', ], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], stackAlerts: ['all'], }, spaces: ['*'], diff --git a/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/defend_insights/get_events/get_file_events_query.ts b/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/defend_insights/get_events/get_file_events_query.ts index fa8f6fa1e33b4..eef2e1ad28f16 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/defend_insights/get_events/get_file_events_query.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/defend_insights/get_events/get_file_events_query.ts @@ -14,7 +14,6 @@ const SIZE = 200; export function getFileEventsQuery({ endpointIds }: { endpointIds: string[] }): SearchRequest { return { allow_no_indices: true, - fields: ['_id', 'agent.id', 'process.executable'], query: { bool: { must: [ @@ -34,15 +33,31 @@ export function getFileEventsQuery({ endpointIds }: { endpointIds: string[] }): ], }, }, - size: SIZE, - sort: [ - { - '@timestamp': { - order: 'desc', + size: 0, // Aggregations only + aggs: { + unique_process_executable: { + terms: { + field: 'process.executable', + size: SIZE, + }, + aggs: { + // Get the latest event for each process.executable + latest_event: { + top_hits: { + size: 1, + sort: [ + { + '@timestamp': { + order: 'desc', + }, + }, + ], + _source: ['_id', 'agent.id', 'process.executable'], // Include only necessary fields + }, + }, }, }, - ], - _source: false, + }, ignore_unavailable: true, index: [FILE_EVENTS_INDEX_PATTERN], }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/defend_insights/get_events/index.test.ts b/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/defend_insights/get_events/index.test.ts index 7c2fd9f61e255..e35a3fee54866 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/defend_insights/get_events/index.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/defend_insights/get_events/index.test.ts @@ -12,6 +12,7 @@ import { DefendInsightType, transformRawData } from '@kbn/elastic-assistant-comm import { InvalidDefendInsightTypeError } from '../errors'; import { getFileEventsQuery } from './get_file_events_query'; import { getAnonymizedEvents } from '.'; +import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; jest.mock('@kbn/elastic-assistant-common', () => { const originalModule = jest.requireActual('@kbn/elastic-assistant-common'); @@ -28,10 +29,46 @@ jest.mock('./get_file_events_query', () => ({ describe('getAnonymizedEvents', () => { let mockEsClient: jest.Mocked; - const mockHits = [ - { _index: 'test-index', fields: { field1: ['value1'] } }, - { _index: 'test-index', fields: { field2: ['value2'] } }, - ]; + const mockAggregations = { + unique_process_executable: { + buckets: [ + { + key: 'process1', + doc_count: 10, + latest_event: { + hits: { + hits: [ + { + _id: 'event1', + _source: { + agent: { id: 'agent1' }, + process: { executable: 'process1' }, + }, + }, + ], + }, + }, + }, + { + key: 'process2', + doc_count: 5, + latest_event: { + hits: { + hits: [ + { + _id: 'event2', + _source: { + agent: { id: 'agent2' }, + process: { executable: 'process2' }, + }, + }, + ], + }, + }, + }, + ], + }, + }; beforeEach(() => { (getFileEventsQuery as jest.Mock).mockReturnValue({ index: 'test-index', body: {} }); @@ -48,9 +85,7 @@ describe('getAnonymizedEvents', () => { skipped: 0, failed: 0, }, - hits: { - hits: mockHits, - }, + aggregations: mockAggregations, }), } as unknown as jest.Mocked; }); @@ -59,17 +94,54 @@ describe('getAnonymizedEvents', () => { jest.clearAllMocks(); }); - it('should return anonymized events successfully', async () => { + it('should return anonymized events successfully from aggregations', async () => { const result = await getAnonymizedEvents({ endpointIds: ['endpoint1'], type: DefendInsightType.Enum.incompatible_antivirus, esClient: mockEsClient, }); - expect(result).toEqual(['anonymized_value1', 'anonymized_value2']); + expect(result).toEqual(['anonymized_event1', 'anonymized_event2']); expect(getFileEventsQuery).toHaveBeenCalledWith({ endpointIds: ['endpoint1'] }); expect(mockEsClient.search).toHaveBeenCalledWith({ index: 'test-index', body: {} }); expect(transformRawData).toHaveBeenCalledTimes(2); + expect(transformRawData).toHaveBeenCalledWith( + expect.objectContaining({ + rawData: expect.objectContaining({ + _id: ['event1'], + }), + }) + ); + }); + + it('should map aggregation response correctly into fileEvents structure', async () => { + await getAnonymizedEvents({ + endpointIds: ['endpoint1'], + type: DefendInsightType.Enum.incompatible_antivirus, + esClient: mockEsClient, + }); + + expect(mockEsClient.search).toHaveBeenCalledWith({ index: 'test-index', body: {} }); + + expect(transformRawData).toHaveBeenCalledWith( + expect.objectContaining({ + rawData: { + _id: ['event1'], + 'agent.id': ['agent1'], + 'process.executable': ['process1'], + }, + }) + ); + + expect(transformRawData).toHaveBeenCalledWith( + expect.objectContaining({ + rawData: { + _id: ['event2'], + 'agent.id': ['agent2'], + 'process.executable': ['process2'], + }, + }) + ); }); it('should throw InvalidDefendInsightTypeError for invalid type', async () => { @@ -81,4 +153,31 @@ describe('getAnonymizedEvents', () => { }) ).rejects.toThrow(InvalidDefendInsightTypeError); }); + + it('should handle empty aggregation response gracefully', async () => { + mockEsClient.search.mockResolvedValueOnce({ + took: 1, + timed_out: false, + _shards: { + total: 1, + successful: 1, + skipped: 0, + failed: 0, + }, + aggregations: { + unique_process_executable: { + buckets: [], + }, + }, + } as unknown as SearchResponse); + + const result = await getAnonymizedEvents({ + endpointIds: ['endpoint1'], + type: DefendInsightType.Enum.incompatible_antivirus, + esClient: mockEsClient, + }); + + expect(result).toEqual([]); + expect(transformRawData).not.toHaveBeenCalled(); + }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/defend_insights/get_events/index.ts b/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/defend_insights/get_events/index.ts index 4d9fcaf89a34a..4f120e8e655f0 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/defend_insights/get_events/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/defend_insights/get_events/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { SearchRequest, SearchResponse } from '@elastic/elasticsearch/lib/api/types'; +import type { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; import type { ElasticsearchClient } from '@kbn/core/server'; import type { Replacements } from '@kbn/elastic-assistant-common'; import type { AnonymizationFieldResponse } from '@kbn/elastic-assistant-common/impl/schemas/anonymization_fields/bulk_crud_anonymization_fields_route.gen'; @@ -20,6 +20,26 @@ import { import { getFileEventsQuery } from './get_file_events_query'; import { InvalidDefendInsightTypeError } from '../errors'; +interface AggregationResponse { + unique_process_executable: { + buckets: Array<{ + key: string; + doc_count: number; + latest_event: { + hits: { + hits: Array<{ + _id: string; + _source: { + agent: { id: string }; + process: { executable: string }; + }; + }>; + }; + }; + }>; + }; +} + export async function getAnonymizedEvents({ endpointIds, type, @@ -70,7 +90,17 @@ const getAnonymized = async ({ onNewReplacements?: (replacements: Replacements) => void; replacements?: Replacements; }): Promise => { - const result = await esClient.search(query); + const result = await esClient.search<{}, AggregationResponse>(query); + const fileEvents = (result.aggregations?.unique_process_executable.buckets ?? []).map( + (bucket) => { + const latestEvent = bucket.latest_event.hits.hits[0]; + return { + _id: [latestEvent._id], + 'agent.id': [latestEvent._source.agent.id], + 'process.executable': [latestEvent._source.process.executable], + }; + } + ); // Accumulate replacements locally so we can, for example use the same // replacement for a hostname when we see it in multiple alerts: @@ -81,13 +111,13 @@ const getAnonymized = async ({ onNewReplacements?.(localReplacements); // invoke the callback with the latest replacements }; - return result.hits?.hits?.map((hit) => + return fileEvents.map((fileEvent) => transformRawData({ anonymizationFields, currentReplacements: localReplacements, // <-- the latest local replacements getAnonymizedValue, onNewReplacements: localOnNewReplacements, // <-- the local callback - rawData: getRawDataOrDefault(hit.fields), + rawData: getRawDataOrDefault(fileEvent), }) ); }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/builders/incompatible_antivirus.test.ts b/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/builders/incompatible_antivirus.test.ts index 41b833be05fc0..08074b6cc91b6 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/builders/incompatible_antivirus.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/builders/incompatible_antivirus.test.ts @@ -7,7 +7,7 @@ import moment from 'moment'; -import type { KibanaRequest } from '@kbn/core/server'; +import type { ElasticsearchClient, KibanaRequest } from '@kbn/core/server'; import type { DefendInsightsPostRequestBody } from '@kbn/elastic-assistant-common'; import { ENDPOINT_ARTIFACT_LISTS } from '@kbn/securitysolution-list-constants'; @@ -30,101 +30,189 @@ jest.mock('../helpers', () => ({ })); describe('buildIncompatibleAntivirusWorkflowInsights', () => { - let params: BuildWorkflowInsightParams; + const mockEndpointAppContextService = createMockEndpointAppContext().service; + mockEndpointAppContextService.getEndpointMetadataService = jest.fn().mockReturnValue({ + getMetadataForEndpoints: jest.fn(), + }); + const endpointMetadataService = + mockEndpointAppContextService.getEndpointMetadataService() as jest.Mocked; - beforeEach(() => { - const mockEndpointAppContextService = createMockEndpointAppContext().service; - mockEndpointAppContextService.getEndpointMetadataService = jest.fn().mockReturnValue({ - getMetadataForEndpoints: jest.fn(), - }); - const endpointMetadataService = - mockEndpointAppContextService.getEndpointMetadataService() as jest.Mocked; - - params = { - defendInsights: [ - { - group: 'AVGAntivirus', - events: [ - { - id: 'lqw5opMB9Ke6SNgnxRSZ', - endpointId: 'f6e2f338-6fb7-4c85-9c23-d20e9f96a051', - value: '/Applications/AVGAntivirus.app/Contents/Backend/services/com.avg.activity', - }, - ], + const generateParams = (signerId?: string): BuildWorkflowInsightParams => ({ + defendInsights: [ + { + group: 'AVGAntivirus', + events: [ + { + id: 'lqw5opMB9Ke6SNgnxRSZ', + endpointId: 'f6e2f338-6fb7-4c85-9c23-d20e9f96a051', + value: '/Applications/AVGAntivirus.app/Contents/Backend/services/com.avg.activity', + ...(signerId ? { signerId } : {}), + }, + ], + }, + ], + request: { + body: { + insightType: 'incompatible_antivirus', + endpointIds: ['endpoint-1'], + apiConfig: { + connectorId: 'connector-id-1', + actionTypeId: 'action-type-id-1', + model: 'model-1', + }, + anonymizationFields: [], + subAction: 'invokeAI', + }, + } as unknown as KibanaRequest, + endpointMetadataService, + esClient: { + search: jest.fn().mockResolvedValue({ + hits: { + hits: [], }, - ], - request: { - body: { - insightType: 'incompatible_antivirus', - endpointIds: ['endpoint-1'], - apiConfig: { - connectorId: 'connector-id-1', - actionTypeId: 'action-type-id-1', - model: 'model-1', + }), + } as unknown as ElasticsearchClient, + }); + + const buildExpectedInsight = (os: string, signerField?: string, signerValue?: string) => + expect.objectContaining({ + '@timestamp': expect.any(moment), + message: 'Incompatible antiviruses detected', + category: Category.Endpoint, + type: 'incompatible_antivirus', + source: { + type: SourceType.LlmConnector, + id: 'connector-id-1', + data_range_start: expect.any(moment), + data_range_end: expect.any(moment), + }, + target: { + type: TargetType.Endpoint, + ids: ['endpoint-1'], + }, + action: { + type: ActionType.Refreshed, + timestamp: expect.any(moment), + }, + value: `AVGAntivirus /Applications/AVGAntivirus.app/Contents/Backend/services/com.avg.activity${ + signerValue ? ` ${signerValue}` : '' + }`, + remediation: { + exception_list_items: [ + { + list_id: ENDPOINT_ARTIFACT_LISTS.trustedApps.id, + name: 'AVGAntivirus', + description: 'Suggested by Security Workflow Insights', + entries: [ + { + field: 'process.executable.caseless', + operator: 'included', + type: 'match', + value: '/Applications/AVGAntivirus.app/Contents/Backend/services/com.avg.activity', + }, + ...(signerField && signerValue + ? [ + { + field: signerField, + operator: 'included', + type: 'match', + value: signerValue, + }, + ] + : []), + ], + tags: ['policy:all'], + os_types: [os], }, - anonymizationFields: [], - subAction: 'invokeAI', + ], + }, + metadata: { + notes: { + llm_model: 'model-1', }, - } as unknown as KibanaRequest, - endpointMetadataService, - }; + display_name: 'AVGAntivirus', + }, + }); + it('should correctly build workflow insights', async () => { (groupEndpointIdsByOS as jest.Mock).mockResolvedValue({ windows: ['endpoint-1'], }); + const params = generateParams(); + const result = await buildIncompatibleAntivirusWorkflowInsights(params); + + expect(result).toEqual([buildExpectedInsight('windows')]); + expect(groupEndpointIdsByOS).toHaveBeenCalledWith( + ['endpoint-1'], + params.endpointMetadataService + ); }); - it('should correctly build workflow insights', async () => { + it('should correctly build workflow insights for Windows with signerId provided', async () => { + (groupEndpointIdsByOS as jest.Mock).mockResolvedValue({ + windows: ['endpoint-1'], + }); + const params = generateParams('test.com'); + + params.esClient.search = jest.fn().mockResolvedValue({ + hits: { + hits: [ + { + _id: 'lqw5opMB9Ke6SNgnxRSZ', + _source: { + process: { + Ext: { + code_signature: { + trusted: true, + subject_name: 'test.com', + }, + }, + }, + }, + }, + ], + }, + }); + const result = await buildIncompatibleAntivirusWorkflowInsights(params); expect(result).toEqual([ - expect.objectContaining({ - '@timestamp': expect.any(moment), - message: 'Incompatible antiviruses detected', - category: Category.Endpoint, - type: 'incompatible_antivirus', - source: { - type: SourceType.LlmConnector, - id: 'connector-id-1', - data_range_start: expect.any(moment), - data_range_end: expect.any(moment), - }, - target: { - type: TargetType.Endpoint, - ids: ['endpoint-1'], - }, - action: { - type: ActionType.Refreshed, - timestamp: expect.any(moment), - }, - value: 'AVGAntivirus', - remediation: { - exception_list_items: [ - { - list_id: ENDPOINT_ARTIFACT_LISTS.trustedApps.id, - name: 'AVGAntivirus', - description: 'Suggested by Security Workflow Insights', - entries: [ - { - field: 'process.executable.caseless', - operator: 'included', - type: 'match', - value: - '/Applications/AVGAntivirus.app/Contents/Backend/services/com.avg.activity', + buildExpectedInsight('windows', 'process.Ext.code_signature', 'test.com'), + ]); + expect(groupEndpointIdsByOS).toHaveBeenCalledWith( + ['endpoint-1'], + params.endpointMetadataService + ); + }); + + it('should correctly build workflow insights for MacOS with signerId provided', async () => { + (groupEndpointIdsByOS as jest.Mock).mockResolvedValue({ + macos: ['endpoint-1'], + }); + + const params = generateParams('test.com'); + + params.esClient.search = jest.fn().mockResolvedValue({ + hits: { + hits: [ + { + _id: 'lqw5opMB9Ke6SNgnxRSZ', + _source: { + process: { + code_signature: { + trusted: true, + subject_name: 'test.com', }, - ], - tags: ['policy:all'], - os_types: ['windows'], + }, }, - ], - }, - metadata: { - notes: { - llm_model: 'model-1', }, - }, - }), - ]); + ], + }, + }); + + const result = await buildIncompatibleAntivirusWorkflowInsights(params); + + expect(result).toEqual([buildExpectedInsight('macos', 'process.code_signature', 'test.com')]); expect(groupEndpointIdsByOS).toHaveBeenCalledWith( ['endpoint-1'], params.endpointMetadataService diff --git a/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/builders/incompatible_antivirus.ts b/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/builders/incompatible_antivirus.ts index 64485995c578d..b53c2d44555bd 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/builders/incompatible_antivirus.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/builders/incompatible_antivirus.ts @@ -6,6 +6,7 @@ */ import moment from 'moment'; +import { get as _get, uniqBy } from 'lodash'; import type { DefendInsight } from '@kbn/elastic-assistant-common'; @@ -15,6 +16,7 @@ import type { SecurityWorkflowInsight } from '../../../../../common/endpoint/typ import type { SupportedHostOsType } from '../../../../../common/endpoint/constants'; import type { BuildWorkflowInsightParams } from '.'; +import { FILE_EVENTS_INDEX_PATTERN } from '../../../../../common/endpoint/constants'; import { ActionType, Category, @@ -23,66 +25,160 @@ import { } from '../../../../../common/endpoint/types/workflow_insights'; import { groupEndpointIdsByOS } from '../helpers'; +interface FileEventDoc { + process: { + code_signature?: { + subject_name: string; + trusted: boolean; + }; + Ext?: { + code_signature?: { + subject_name: string; + trusted: boolean; + }; + }; + }; +} + export async function buildIncompatibleAntivirusWorkflowInsights( params: BuildWorkflowInsightParams ): Promise { const currentTime = moment(); - const { defendInsights, request, endpointMetadataService } = params; + const { defendInsights, request, endpointMetadataService, esClient } = params; const { insightType, endpointIds, apiConfig } = request.body; const osEndpointIdsMap = await groupEndpointIdsByOS(endpointIds, endpointMetadataService); - return defendInsights.flatMap((defendInsight: DefendInsight) => { - const filePaths = Array.from(new Set((defendInsight.events ?? []).map((event) => event.value))); - - return Object.keys(osEndpointIdsMap).flatMap((os) => - filePaths.map((filePath) => ({ - '@timestamp': currentTime, - // TODO add i18n support - message: 'Incompatible antiviruses detected', - category: Category.Endpoint, - type: insightType, - source: { - type: SourceType.LlmConnector, - id: apiConfig.connectorId, - // TODO use actual time range when we add support - data_range_start: currentTime, - data_range_end: currentTime.clone().add(24, 'hours'), - }, - target: { - type: TargetType.Endpoint, - ids: endpointIds, - }, - action: { - type: ActionType.Refreshed, - timestamp: currentTime, - }, - value: defendInsight.group, - remediation: { - exception_list_items: [ - { - list_id: ENDPOINT_ARTIFACT_LISTS.trustedApps.id, - name: defendInsight.group, - description: 'Suggested by Security Workflow Insights', - entries: [ + + const insightsPromises = defendInsights.map( + async (defendInsight: DefendInsight): Promise => { + const uniqueFilePathsInsights = uniqBy(defendInsight.events, 'value'); + const eventIds = Array.from(new Set(uniqueFilePathsInsights.map((event) => event.id))); + + const codeSignaturesHits = ( + await esClient.search({ + index: FILE_EVENTS_INDEX_PATTERN, + query: { + bool: { + must: [ { - field: 'process.executable.caseless', - operator: 'included', - type: 'match', - value: filePath, + terms: { + _id: eventIds, + }, + }, + { + bool: { + should: [ + { + term: { + 'process.code_signature.trusted': true, + }, + }, + { + term: { + 'process.Ext.code_signature.trusted': true, + }, + }, + ], + }, }, ], - // TODO add per policy support - tags: ['policy:all'], - os_types: [os as SupportedHostOsType], }, - ], - }, - metadata: { - notes: { - llm_model: apiConfig.model ?? '', }, - }, - })) - ); - }); + }) + ).hits.hits; + + const createRemediation = ( + filePath: string, + os: string, + signatureField?: string, + signatureValue?: string + ): SecurityWorkflowInsight => { + return { + '@timestamp': currentTime, + // TODO add i18n support + message: 'Incompatible antiviruses detected', + category: Category.Endpoint, + type: insightType, + source: { + type: SourceType.LlmConnector, + id: apiConfig.connectorId, + // TODO use actual time range when we add support + data_range_start: currentTime, + data_range_end: currentTime.clone().add(24, 'hours'), + }, + target: { + type: TargetType.Endpoint, + ids: endpointIds, + }, + action: { + type: ActionType.Refreshed, + timestamp: currentTime, + }, + value: `${defendInsight.group} ${filePath}${signatureValue ? ` ${signatureValue}` : ''}`, + metadata: { + notes: { + llm_model: apiConfig.model ?? '', + }, + display_name: defendInsight.group, + }, + remediation: { + exception_list_items: [ + { + list_id: ENDPOINT_ARTIFACT_LISTS.trustedApps.id, + name: defendInsight.group, + description: 'Suggested by Security Workflow Insights', + entries: [ + { + field: 'process.executable.caseless', + operator: 'included' as const, + type: 'match' as const, + value: filePath, + }, + ...(signatureField && signatureValue + ? [ + { + field: signatureField, + operator: 'included' as const, + type: 'match' as const, + value: signatureValue, + }, + ] + : []), + ], + // TODO add per policy support + tags: ['policy:all'], + os_types: [os as SupportedHostOsType], + }, + ], + }, + }; + }; + + return Object.keys(osEndpointIdsMap).flatMap((os): SecurityWorkflowInsight[] => { + return uniqueFilePathsInsights.map((insight) => { + const { value: filePath, id } = insight; + + if (codeSignaturesHits.length) { + const codeSignatureSearchHit = codeSignaturesHits.find((hit) => hit._id === id); + + if (codeSignatureSearchHit) { + const extPath = os === 'windows' ? '.Ext' : ''; + const field = `process${extPath}.code_signature`; + const value = _get( + codeSignatureSearchHit, + `_source.${field}.subject_name`, + 'invalid subject name' + ); + return createRemediation(filePath, os, field, value); + } + } + + return createRemediation(filePath, os); + }); + }); + } + ); + + const insightsArr = await Promise.all(insightsPromises); + return insightsArr.flat(); } diff --git a/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/builders/index.ts b/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/builders/index.ts index 1f00d152f1f12..a19e800629598 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/builders/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/builders/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { KibanaRequest } from '@kbn/core/server'; +import type { ElasticsearchClient, KibanaRequest } from '@kbn/core/server'; import type { DefendInsight, DefendInsightsPostRequestBody } from '@kbn/elastic-assistant-common'; @@ -21,6 +21,7 @@ export interface BuildWorkflowInsightParams { defendInsights: DefendInsight[]; request: KibanaRequest; endpointMetadataService: EndpointMetadataService; + esClient: ElasticsearchClient; } export function buildWorkflowInsights( diff --git a/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/helpers.ts b/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/helpers.ts index f7b477a17018d..0e508c5bcfed7 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/helpers.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/helpers.ts @@ -149,3 +149,14 @@ export function generateInsightId(insight: SecurityWorkflowInsight): string { return hash.digest('hex'); } + +export function getUniqueInsights(insights: SecurityWorkflowInsight[]): SecurityWorkflowInsight[] { + const uniqueInsights: { [key: string]: SecurityWorkflowInsight } = {}; + for (const insight of insights) { + const id = generateInsightId(insight); + if (!uniqueInsights[id]) { + uniqueInsights[id] = insight; + } + } + return Object.values(uniqueInsights); +} diff --git a/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/index.test.ts b/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/index.test.ts index 849c6431a09a8..cca105152d3fe 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/index.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/index.test.ts @@ -223,17 +223,19 @@ describe('SecurityWorkflowInsightsService', () => { describe('createFromDefendInsights', () => { it('should create workflow insights from defend insights', async () => { + const insight = { + group: 'AVGAntivirus', + events: [ + { + id: 'lqw5opMB9Ke6SNgnxRSZ', + endpointId: 'f6e2f338-6fb7-4c85-9c23-d20e9f96a051', + value: '/Applications/AVGAntivirus.app/Contents/Backend/services/com.avg.activity', + }, + ], + }; const defendInsights: DefendInsight[] = [ - { - group: 'AVGAntivirus', - events: [ - { - id: 'lqw5opMB9Ke6SNgnxRSZ', - endpointId: 'f6e2f338-6fb7-4c85-9c23-d20e9f96a051', - value: '/Applications/AVGAntivirus.app/Contents/Backend/services/com.avg.activity', - }, - ], - }, + insight, + insight, // intentional dupe to confirm de-duping ]; const request = {} as KibanaRequest; @@ -266,6 +268,7 @@ describe('SecurityWorkflowInsightsService', () => { defendInsights, request, endpointMetadataService: expect.any(Object), + esClient, }); expect(result).toEqual(workflowInsights.map(() => esClientIndexResp)); }); @@ -283,8 +286,10 @@ describe('SecurityWorkflowInsightsService', () => { expect(esClient.index).toHaveBeenCalledTimes(1); expect(esClient.index).toHaveBeenCalledWith({ index: DATA_STREAM_NAME, - body: { ...insight, id: generateInsightId(insight) }, + id: generateInsightId(insight), + body: insight, refresh: 'wait_for', + op_type: 'create', }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/index.ts b/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/index.ts index 1baeaf74e00f0..5714f25c92be2 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/endpoint/services/workflow_insights/index.ts @@ -23,7 +23,13 @@ import type { import type { EndpointAppContextService } from '../../endpoint_app_context_services'; import { SecurityWorkflowInsightsFailedInitialized } from './errors'; -import { buildEsQueryParams, createDatastream, createPipeline, generateInsightId } from './helpers'; +import { + buildEsQueryParams, + createDatastream, + createPipeline, + generateInsightId, + getUniqueInsights, +} from './helpers'; import { DATA_STREAM_NAME } from './constants'; import { buildWorkflowInsights } from './builders'; @@ -128,8 +134,10 @@ class SecurityWorkflowInsightsService { defendInsights, request, endpointMetadataService: this.endpointContext.getEndpointMetadataService(), + esClient: this.esClient, }); - return Promise.all(workflowInsights.map((insight) => this.create(insight))); + const uniqueInsights = getUniqueInsights(workflowInsights); + return Promise.all(uniqueInsights.map((insight) => this.create(insight))); } public async create(insight: SecurityWorkflowInsight): Promise { @@ -145,8 +153,10 @@ class SecurityWorkflowInsightsService { const response = await this.esClient.index({ index: DATA_STREAM_NAME, - body: { ...insight, id }, + id, + body: insight, refresh: 'wait_for', + op_type: 'create', }); return response; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/asset_inventory_data_client.mock.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/asset_inventory_data_client.mock.ts new file mode 100644 index 0000000000000..459301a5eed1b --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/asset_inventory_data_client.mock.ts @@ -0,0 +1,17 @@ +/* + * 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 { AssetInventoryDataClient } from './asset_inventory_data_client'; + +const createAssetInventoryDataClientMock = () => + ({ + init: jest.fn(), + enable: jest.fn(), + delete: jest.fn(), + } as unknown as jest.Mocked); + +export const AssetInventoryDataClientMock = { create: createAssetInventoryDataClientMock }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/asset_inventory_data_client.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/asset_inventory_data_client.ts new file mode 100644 index 0000000000000..88ff64bb70793 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/asset_inventory_data_client.ts @@ -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 type { Logger, ElasticsearchClient, IScopedClusterClient } from '@kbn/core/server'; + +import type { ExperimentalFeatures } from '../../../common'; + +import { createKeywordBuilderPipeline, deleteKeywordBuilderPipeline } from './ingest_pipelines'; + +interface AssetInventoryClientOpts { + logger: Logger; + clusterClient: IScopedClusterClient; + experimentalFeatures: ExperimentalFeatures; +} + +// AssetInventoryDataClient is responsible for managing the asset inventory, +// including initializing and cleaning up resources such as Elasticsearch ingest pipelines. +export class AssetInventoryDataClient { + private esClient: ElasticsearchClient; + + constructor(private readonly options: AssetInventoryClientOpts) { + const { clusterClient } = options; + this.esClient = clusterClient.asCurrentUser; + } + + // Enables the asset inventory by deferring the initialization to avoid blocking the main thread. + public async enable() { + // Utility function to defer execution to the next tick using setTimeout. + const run = (fn: () => Promise) => + new Promise((resolve) => setTimeout(() => fn().then(resolve), 0)); + + // Defer and execute the initialization process. + await run(() => this.init()); + + return { succeeded: true }; + } + + // Initializes the asset inventory by validating experimental feature flags and triggering asynchronous setup. + public async init() { + const { experimentalFeatures, logger } = this.options; + + if (!experimentalFeatures.assetInventoryStoreEnabled) { + throw new Error('Universal entity store is not enabled'); + } + + logger.debug(`Initializing asset inventory`); + + this.asyncSetup().catch((e) => + logger.error(`Error during async setup of asset inventory: ${e.message}`) + ); + } + + // Sets up the necessary resources for asset inventory, including creating Elasticsearch ingest pipelines. + private async asyncSetup() { + const { logger } = this.options; + try { + logger.debug('creating keyword builder pipeline'); + await createKeywordBuilderPipeline({ + logger, + esClient: this.esClient, + }); + logger.debug('keyword builder pipeline created'); + } catch (err) { + logger.error(`Error initializing asset inventory: ${err.message}`); + await this.delete(); + } + } + + // Cleans up the resources associated with the asset inventory, such as removing the ingest pipeline. + public async delete() { + const { logger } = this.options; + + logger.debug(`Deleting asset inventory`); + + try { + logger.debug(`Deleting asset inventory keyword builder pipeline`); + + await deleteKeywordBuilderPipeline({ + logger, + esClient: this.esClient, + }).catch((err) => { + logger.error('Error on deleting keyword builder pipeline', err); + }); + + logger.debug(`Deleted asset inventory`); + return { deleted: true }; + } catch (err) { + logger.error(`Error deleting asset inventory: ${err.message}`); + throw err; + } + } +} diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/ingest_pipelines/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/ingest_pipelines/index.ts new file mode 100644 index 0000000000000..41c9c45587e1c --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/ingest_pipelines/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './keyword_builder_ingest_pipeline'; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/ingest_pipelines/keyword_builder_ingest_pipeline.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/ingest_pipelines/keyword_builder_ingest_pipeline.ts new file mode 100644 index 0000000000000..5b2ca91be98bb --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/ingest_pipelines/keyword_builder_ingest_pipeline.ts @@ -0,0 +1,167 @@ +/* + * 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 { ElasticsearchClient, Logger } from '@kbn/core/server'; +import type { IngestProcessorContainer } from '@elastic/elasticsearch/lib/api/types'; + +const PIPELINE_ID = 'entity-keyword-builder@platform'; + +export const buildIngestPipeline = (): IngestProcessorContainer[] => { + return [ + { + script: { + lang: 'painless', + on_failure: [ + { + set: { + field: 'error.message', + value: + 'Processor {{ _ingest.on_failure_processor_type }} with tag {{ _ingest.on_failure_processor_tag }} in pipeline {{ _ingest.on_failure_pipeline }} failed with message {{ _ingest.on_failure_message }}', + }, + }, + ], + + // There are two layers of language to string scape on this script. + // - One is in javascript + // - Another one is in painless. + // + // .e.g, in painless we want the following line: + // entry.getKey().replace("\"", "\\\""); + // + // To do so we must scape each backslash in javascript, otherwise the backslashes will only scape the next character + // and the backslashes won't end up in the painless layer + // + // The code then becomes: + // entry.getKey().replace("\\"", "\\\\\\""); + // That is one extra backslash per backslash (there is no need to scape quotes in the javascript layer) + source: ` + String jsonFromMap(Map map) { + StringBuilder json = new StringBuilder("{"); + boolean first = true; + for (entry in map.entrySet()) { + if (!first) { + json.append(","); + } + first = false; + String key = entry.getKey().replace("\\"", "\\\\\\""); + Object value = entry.getValue(); + json.append("\\"").append(key).append("\\":"); + + if (value instanceof String) { + String escapedValue = ((String) value).replace("\\"", "\\\\\\"").replace("=", ":"); + json.append("\\"").append(escapedValue).append("\\""); + } else if (value instanceof Map) { + json.append(jsonFromMap((Map) value)); + } else if (value instanceof List) { + json.append(jsonFromList((List) value)); + } else if (value instanceof Boolean || value instanceof Number) { + json.append(value.toString()); + } else { + // For other types, treat as string + String escapedValue = value.toString().replace("\\"", "\\\\\\"").replace("=", ":"); + json.append("\\"").append(escapedValue).append("\\""); + } + } + json.append("}"); + return json.toString(); + } + + String jsonFromList(List list) { + StringBuilder json = new StringBuilder("["); + boolean first = true; + for (item in list) { + if (!first) { + json.append(","); + } + first = false; + if (item instanceof String) { + String escapedItem = ((String) item).replace("\\"", "\\\\\\"").replace("=", ":"); + json.append("\\"").append(escapedItem).append("\\""); + } else if (item instanceof Map) { + json.append(jsonFromMap((Map) item)); + } else if (item instanceof List) { + json.append(jsonFromList((List) item)); + } else if (item instanceof Boolean || item instanceof Number) { + json.append(item.toString()); + } else { + // For other types, treat as string + String escapedItem = item.toString().replace("\\"", "\\\\\\"").replace("=", ":"); + json.append("\\"").append(escapedItem).append("\\""); + } + } + json.append("]"); + return json.toString(); + } + + if (ctx.entities?.metadata == null) { + return; + } + + def keywords = []; + for (key in ctx.entities.metadata.keySet()) { + def value = ctx.entities.metadata[key]; + def metadata = jsonFromMap([key: value]); + keywords.add(metadata); + } + + ctx['entities']['keyword'] = keywords; + `, + }, + }, + { + set: { + field: 'event.ingested', + value: '{{{_ingest.timestamp}}}', + }, + }, + ]; +}; + +// developing the pipeline is a bit tricky, so we have a debug mode +// set xpack.securitySolution.entityAnalytics.entityStore.developer.pipelineDebugMode +// to true to keep the enrich field and the context field in the document to help with debugging. +export const createKeywordBuilderPipeline = async ({ + logger, + esClient, +}: { + logger: Logger; + esClient: ElasticsearchClient; +}) => { + const pipeline = { + id: PIPELINE_ID, + body: { + _meta: { + managed_by: 'entity_store', + managed: true, + }, + description: `Serialize entities.metadata into a keyword field`, + processors: buildIngestPipeline(), + }, + }; + + logger.debug(`Attempting to create pipeline: ${JSON.stringify(pipeline)}`); + + await esClient.ingest.putPipeline(pipeline); +}; + +export const deleteKeywordBuilderPipeline = ({ + logger, + esClient, +}: { + logger: Logger; + esClient: ElasticsearchClient; +}) => { + logger.debug(`Attempting to delete pipeline: ${PIPELINE_ID}`); + return esClient.ingest.deletePipeline( + { + id: PIPELINE_ID, + }, + { + ignore: [404], + } + ); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/routes/delete.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/routes/delete.ts new file mode 100644 index 0000000000000..048886ccea252 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/routes/delete.ts @@ -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 type { Logger } from '@kbn/core/server'; +import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils'; +import { transformError } from '@kbn/securitysolution-es-utils'; +import { API_VERSIONS } from '../../../../common/constants'; +import type { AssetInventoryRoutesDeps } from '../types'; + +export const deleteAssetInventoryRoute = ( + router: AssetInventoryRoutesDeps['router'], + logger: Logger +) => { + router.versioned + .delete({ + access: 'public', + path: '/api/asset_inventory/delete', + security: { + authz: { + requiredPrivileges: ['securitySolution'], + }, + }, + }) + .addVersion( + { + version: API_VERSIONS.public.v1, + // TODO: create validation + validate: false, + }, + + async (context, request, response) => { + const siemResponse = buildSiemResponse(response); + + try { + const secSol = await context.securitySolution; + const body = await secSol.getAssetInventoryClient().delete(); + + return response.ok({ body }); + } catch (e) { + logger.error('Error in DeleteEntityEngine:', e); + const error = transformError(e); + return siemResponse.error({ + statusCode: error.statusCode, + body: error.message, + }); + } + } + ); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/routes/enablement.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/routes/enablement.ts new file mode 100644 index 0000000000000..d3cc935eb5a16 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/routes/enablement.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 { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils'; +import { transformError } from '@kbn/securitysolution-es-utils'; +import type { Logger } from '@kbn/core/server'; +import { API_VERSIONS } from '../../../../common/constants'; + +import type { AssetInventoryRoutesDeps } from '../types'; + +export const enableAssetInventoryRoute = ( + router: AssetInventoryRoutesDeps['router'], + logger: Logger, + config: AssetInventoryRoutesDeps['config'] +) => { + router.versioned + .post({ + access: 'public', + path: '/api/asset_inventory/enable', + security: { + authz: { + requiredPrivileges: ['securitySolution'], + }, + }, + }) + .addVersion( + { + version: API_VERSIONS.public.v1, + // TODO: create validation + validate: false, + }, + + async (context, request, response) => { + const siemResponse = buildSiemResponse(response); + const secSol = await context.securitySolution; + + try { + const body = await secSol.getAssetInventoryClient().enable(); + + return response.ok({ body }); + } catch (e) { + const error = transformError(e); + logger.error(`Error initializing asset inventory: ${error.message}`); + return siemResponse.error({ + statusCode: error.statusCode, + body: error.message, + }); + } + } + ); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/routes/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/routes/index.ts new file mode 100644 index 0000000000000..f3d46bd456e7f --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/routes/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { registerAssetInventoryRoutes } from './register_asset_inventory_routes'; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/routes/register_asset_inventory_routes.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/routes/register_asset_inventory_routes.ts new file mode 100644 index 0000000000000..b65c91053a361 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/routes/register_asset_inventory_routes.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { AssetInventoryRoutesDeps } from '../types'; +import { deleteAssetInventoryRoute } from './delete'; +import { enableAssetInventoryRoute } from './enablement'; + +export const registerAssetInventoryRoutes = ({ + router, + logger, + config, +}: AssetInventoryRoutesDeps) => { + enableAssetInventoryRoute(router, logger, config); + deleteAssetInventoryRoute(router, logger); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/types.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/types.ts new file mode 100644 index 0000000000000..a44231e946487 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/asset_inventory/types.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { Logger } from '@kbn/core/server'; +import type { SecuritySolutionPluginRouter } from '../../types'; +import type { ConfigType } from '../../config'; + +export interface AssetInventoryRoutesDeps { + router: SecuritySolutionPluginRouter; + logger: Logger; + config: ConfigType; +} diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/diffable_rule_fields_mappings.test.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/diffable_rule_fields_mappings.test.ts index 95495ebea0d9d..ce628b0d07b35 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/diffable_rule_fields_mappings.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/diffable_rule_fields_mappings.test.ts @@ -8,8 +8,23 @@ import { transformDiffableFieldValues } from './diffable_rule_fields_mappings'; describe('transformDiffableFieldValues', () => { - it('transforms rule_schedule into "from" value', () => { - const result = transformDiffableFieldValues('from', { interval: '5m', lookback: '4m' }); - expect(result).toEqual({ type: 'TRANSFORMED_FIELD', value: 'now-540s' }); + it('does NOT transform "from" in rule_schedule', () => { + const result = transformDiffableFieldValues('from', { + interval: '5m', + from: 'now-10m', + to: 'now', + }); + + expect(result).toEqual({ type: 'NON_TRANSFORMED_FIELD' }); + }); + + it('does NOT transform "to" in rule_schedule', () => { + const result = transformDiffableFieldValues('to', { + interval: '5m', + from: 'now-10m', + to: 'now', + }); + + expect(result).toEqual({ type: 'NON_TRANSFORMED_FIELD' }); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/diffable_rule_fields_mappings.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/diffable_rule_fields_mappings.ts index 86ba3e5dd6bee..32ba541dcd3b6 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/diffable_rule_fields_mappings.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/diffable_rule_fields_mappings.ts @@ -5,8 +5,8 @@ * 2.0. */ import { get, has } from 'lodash'; +import type { RuleSchedule } from '../../../../../../common/api/detection_engine/model/rule_schema/rule_schedule'; import type { - RuleSchedule, DataSourceIndexPatterns, DataSourceDataView, InlineKqlQuery, @@ -15,7 +15,6 @@ import type { } from '../../../../../../common/api/detection_engine'; import { type AllFieldsDiff } from '../../../../../../common/api/detection_engine'; import type { PrebuiltRuleAsset } from '../../model/rule_assets/prebuilt_rule_asset'; -import { calculateFromValue } from '../../../rule_types/utils/utils'; /** * Retrieves and transforms the value for a specific field from a DiffableRule group. @@ -32,11 +31,6 @@ import { calculateFromValue } from '../../../rule_types/utils/utils'; * mapDiffableRuleFieldValueToRuleSchema('index', { index_patterns: ['logs-*'] }) * // Returns: ['logs-*'] * - * @example - * // For a 'from' field in a rule schedule - * mapDiffableRuleFieldValueToRuleSchema('from', { interval: '5d', lookback: '30d' }) - * // Returns: 'now-30d' - * */ export const mapDiffableRuleFieldValueToRuleSchemaFormat = ( fieldName: keyof PrebuiltRuleAsset, @@ -142,8 +136,8 @@ const SUBFIELD_MAPPING: Record = { timeline_id: 'timeline_id', timeline_title: 'timeline_title', interval: 'interval', - from: 'lookback', - to: 'lookback', + from: 'from', + to: 'to', }; /** @@ -157,10 +151,6 @@ const SUBFIELD_MAPPING: Record = { * mapRuleFieldToDiffableRuleSubfield('index') * // Returns: 'index_patterns' * - * @example - * mapRuleFieldToDiffableRuleSubfield('from') - * // Returns: 'lookback' - * */ export function mapRuleFieldToDiffableRuleSubfield(fieldName: string): string { return SUBFIELD_MAPPING[fieldName] || fieldName; @@ -190,11 +180,6 @@ type TransformValuesReturnType = * - If not transformed: { type: 'NON_TRANSFORMED_FIELD' } * * @example - * // Transforms 'from' field - * transformDiffableFieldValues('from', { lookback: '30d' }) - * // Returns: { type: 'TRANSFORMED_FIELD', value: 'now-30d' } - * - * @example * // Transforms 'saved_id' field for inline queries * transformDiffableFieldValues('saved_id', { type: 'inline_query', ... }) * // Returns: { type: 'TRANSFORMED_FIELD', value: undefined } @@ -204,12 +189,7 @@ export const transformDiffableFieldValues = ( fieldName: string, diffableFieldValue: RuleSchedule | InlineKqlQuery | unknown ): TransformValuesReturnType => { - if (fieldName === 'from' && isRuleSchedule(diffableFieldValue)) { - const from = calculateFromValue(diffableFieldValue.interval, diffableFieldValue.lookback); - return { type: 'TRANSFORMED_FIELD', value: from }; - } else if (fieldName === 'to') { - return { type: 'TRANSFORMED_FIELD', value: `now` }; - } else if (fieldName === 'saved_id' && isInlineQuery(diffableFieldValue)) { + if (fieldName === 'saved_id' && isInlineQuery(diffableFieldValue)) { // saved_id should be set only for rules with SavedKqlQuery, undefined otherwise return { type: 'TRANSFORMED_FIELD', value: undefined }; } else if (fieldName === 'data_view_id' && isDataSourceIndexPatterns(diffableFieldValue)) { @@ -221,10 +201,6 @@ export const transformDiffableFieldValues = ( return { type: 'NON_TRANSFORMED_FIELD' }; }; -function isRuleSchedule(value: unknown): value is RuleSchedule { - return typeof value === 'object' && value !== null && 'lookback' in value; -} - function isInlineQuery(value: unknown): value is InlineKqlQuery { return ( typeof value === 'object' && value !== null && 'type' in value && value.type === 'inline_query' diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_context.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_context.ts index e8a1e915f43dd..e31782c13cd1d 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_context.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_context.ts @@ -43,6 +43,7 @@ import { detectionRulesClientMock } from '../../rule_management/logic/detection_ import { packageServiceMock } from '@kbn/fleet-plugin/server/services/epm/package_service.mock'; import type { EndpointInternalFleetServicesInterface } from '../../../../endpoint/services/fleet'; import { siemMigrationsServiceMock } from '../../../siem_migrations/__mocks__/mocks'; +import { AssetInventoryDataClientMock } from '../../../asset_inventory/asset_inventory_data_client.mock'; export const createMockClients = () => { const core = coreMock.createRequestHandlerContext(); @@ -81,6 +82,7 @@ export const createMockClients = () => { }, siemRuleMigrationsClient: siemMigrationsServiceMock.createRulesClient(), getInferenceClient: jest.fn(), + assetInventoryDataClient: AssetInventoryDataClientMock.create(), }; }; @@ -169,6 +171,7 @@ const createSecuritySolutionRequestContextMock = ( getEntityStoreDataClient: jest.fn(() => clients.entityStoreDataClient), getSiemRuleMigrationsClient: jest.fn(() => clients.siemRuleMigrationsClient), getInferenceClient: jest.fn(() => clients.getInferenceClient()), + getAssetInventoryClient: jest.fn(() => clients.assetInventoryDataClient), }; }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts index aa63359b6ccb1..b82c1f942fafb 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts @@ -9,6 +9,7 @@ import { isEmpty, partition } from 'lodash'; import agent from 'elastic-apm-node'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { IndexPatternsFetcher } from '@kbn/data-plugin/server'; import { TIMESTAMP } from '@kbn/rule-data-utils'; import { createPersistenceRuleTypeWrapper } from '@kbn/rule-registry-plugin/server'; import { buildExceptionFilter } from '@kbn/lists-plugin/server/services/exception_lists'; @@ -257,16 +258,20 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = let skipExecution: boolean = false; try { if (!isMachineLearningParams(params)) { - const privileges = await checkPrivilegesFromEsClient(esClient, inputIndex); + const indexPatterns = new IndexPatternsFetcher(scopedClusterClient.asInternalUser); + const existingIndices = await indexPatterns.getExistingIndices(inputIndex); - const readIndexWarningMessage = await hasReadIndexPrivileges({ - privileges, - ruleExecutionLogger, - uiSettingsClient, - }); + if (existingIndices.length > 0) { + const privileges = await checkPrivilegesFromEsClient(esClient, existingIndices); + const readIndexWarningMessage = await hasReadIndexPrivileges({ + privileges, + ruleExecutionLogger, + uiSettingsClient, + }); - if (readIndexWarningMessage != null) { - wrapperWarnings.push(readIndexWarningMessage); + if (readIndexWarningMessage != null) { + wrapperWarnings.push(readIndexWarningMessage); + } } const timestampFieldCaps = await withSecuritySpan('fieldCaps', () => diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/__snapshots__/build_alert.test.ts.snap b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/__snapshots__/build_alert.test.ts.snap index 25d08db218f20..3cb60ffd29b4e 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/__snapshots__/build_alert.test.ts.snap +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/__snapshots__/build_alert.test.ts.snap @@ -218,6 +218,9 @@ Object { "kibana.space_ids": Array [ "default", ], + "service.asset.criticality": undefined, + "service.risk.calculated_level": undefined, + "service.risk.calculated_score_norm": undefined, "user.asset.criticality": undefined, "user.risk.calculated_level": undefined, "user.risk.calculated_score_norm": undefined, @@ -442,6 +445,9 @@ Object { "kibana.space_ids": Array [ "default", ], + "service.asset.criticality": undefined, + "service.risk.calculated_level": undefined, + "service.risk.calculated_score_norm": undefined, "user.asset.criticality": undefined, "user.risk.calculated_level": undefined, "user.risk.calculated_score_norm": undefined, diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts index e49070f483f97..c13028e9d3c0a 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts @@ -88,6 +88,9 @@ import { ALERT_HOST_RISK_SCORE_CALCULATED_SCORE_NORM, ALERT_USER_RISK_SCORE_CALCULATED_LEVEL, ALERT_USER_RISK_SCORE_CALCULATED_SCORE_NORM, + ALERT_SERVICE_CRITICALITY, + ALERT_SERVICE_RISK_SCORE_CALCULATED_LEVEL, + ALERT_SERVICE_RISK_SCORE_CALCULATED_SCORE_NORM, } from '../../../../../../common/field_maps/field_names'; import type { CompleteRule, RuleParams } from '../../../rule_schema'; import { commonParamsCamelToSnake, typeSpecificCamelToSnake } from '../../../rule_management'; @@ -288,10 +291,13 @@ export const buildAlertFields = ({ [LEGACY_ALERT_USER_CRITICALITY]: undefined, [ALERT_HOST_CRITICALITY]: undefined, [ALERT_USER_CRITICALITY]: undefined, + [ALERT_SERVICE_CRITICALITY]: undefined, [ALERT_HOST_RISK_SCORE_CALCULATED_LEVEL]: undefined, [ALERT_HOST_RISK_SCORE_CALCULATED_SCORE_NORM]: undefined, [ALERT_USER_RISK_SCORE_CALCULATED_LEVEL]: undefined, [ALERT_USER_RISK_SCORE_CALCULATED_SCORE_NORM]: undefined, + [ALERT_SERVICE_RISK_SCORE_CALCULATED_LEVEL]: undefined, + [ALERT_SERVICE_RISK_SCORE_CALCULATED_SCORE_NORM]: undefined, [ALERT_INTENDED_TIMESTAMP]: intendedTimestamp ? intendedTimestamp.toISOString() : timestamp, [ALERT_RULE_EXECUTION_TYPE]: intendedTimestamp ? RULE_EXECUTION_TYPE.MANUAL diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.test.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.test.ts index 84f5817413a4a..3de8c6227f48b 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.test.ts @@ -21,6 +21,7 @@ import { QUERY_RULE_TYPE_ID } from '@kbn/securitysolution-rules'; import { hasTimestampFields } from '../utils/utils'; import { RuleExecutionStatusEnum } from '../../../../../common/api/detection_engine'; +const actualHasTimestampFields = jest.requireActual('../utils/utils').hasTimestampFields; jest.mock('../utils/utils', () => ({ ...jest.requireActual('../utils/utils'), getExceptions: () => [], @@ -114,7 +115,8 @@ describe('Custom Query Alerts', () => { expect(eventsTelemetry.queueTelemetryEvents).not.toHaveBeenCalled(); }); - it('sends an alert when events are found', async () => { + it('short-circuits and writes a warning if no indices are found', async () => { + (hasTimestampFields as jest.Mock).mockImplementationOnce(actualHasTimestampFields); // default behavior will produce a 'no indices found' result from this helper const queryAlertType = securityRuleTypeWrapper( createQueryAlertType({ eventsTelemetry, @@ -156,6 +158,77 @@ describe('Custom Query Alerts', () => { await executor({ params }); + expect((await ruleDataClient.getWriter()).bulk).not.toHaveBeenCalled(); + expect(eventsTelemetry.sendAsync).not.toHaveBeenCalled(); + expect(mockedStatusLogger.logStatusChange).toHaveBeenCalledWith( + expect.objectContaining({ + newStatus: RuleExecutionStatusEnum['partial failure'], + message: + 'This rule is attempting to query data from Elasticsearch indices listed in the "Index patterns" section of the rule definition, however no index matching: ["auditbeat-*","filebeat-*","packetbeat-*","winlogbeat-*"] was found. This warning will continue to appear until a matching index is created or this rule is disabled.', + }) + ); + }); + + it('sends an alert when events are found', async () => { + const queryAlertType = securityRuleTypeWrapper( + createQueryAlertType({ + eventsTelemetry, + licensing, + scheduleNotificationResponseActionsService: () => null, + experimentalFeatures: allowedExperimentalValues, + logger, + version: '1.0.0', + id: QUERY_RULE_TYPE_ID, + name: 'Custom Query Rule', + }) + ); + + alerting.registerType(queryAlertType); + + const params = getQueryRuleParams(); + + // mock field caps so as not to short-circuit on "no indices found" + services.scopedClusterClient.asInternalUser.fieldCaps.mockResolvedValueOnce({ + // @ts-expect-error our fieldCaps mock only seems to use the last value of the overloaded FieldCapsApi + body: { + indices: params.index!, + fields: { + _id: { + _id: { + type: '_id', + metadata_field: true, + searchable: true, + aggregatable: false, + }, + }, + }, + }, + }); + + services.scopedClusterClient.asCurrentUser.search.mockReturnValue( + elasticsearchClientMock.createSuccessTransportRequestPromise({ + hits: { + hits: [sampleDocNoSortId()], + sequences: [], + events: [], + total: { + relation: 'eq', + value: 1, + }, + }, + took: 0, + timed_out: false, + _shards: { + failed: 0, + skipped: 0, + successful: 1, + total: 1, + }, + }) + ); + + await executor({ params }); + expect((await ruleDataClient.getWriter()).bulk).toHaveBeenCalled(); expect(eventsTelemetry.sendAsync).toHaveBeenCalled(); }); diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/__mocks__/alerts.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/__mocks__/alerts.ts index 8e43453dd086d..dac347d14f78f 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/__mocks__/alerts.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/__mocks__/alerts.ts @@ -78,6 +78,9 @@ import { ALERT_HOST_RISK_SCORE_CALCULATED_SCORE_NORM, ALERT_USER_RISK_SCORE_CALCULATED_LEVEL, ALERT_USER_RISK_SCORE_CALCULATED_SCORE_NORM, + ALERT_SERVICE_CRITICALITY, + ALERT_SERVICE_RISK_SCORE_CALCULATED_LEVEL, + ALERT_SERVICE_RISK_SCORE_CALCULATED_SCORE_NORM, } from '../../../../../../../common/field_maps/field_names'; export const createAlert = ( @@ -214,6 +217,9 @@ export const createAlert = ( [ALERT_USER_RISK_SCORE_CALCULATED_SCORE_NORM]: undefined, [ALERT_INTENDED_TIMESTAMP]: '2020-04-20T21:27:45+0000', [ALERT_RULE_EXECUTION_TYPE]: 'scheduled', + [ALERT_SERVICE_CRITICALITY]: undefined, + [ALERT_SERVICE_RISK_SCORE_CALCULATED_LEVEL]: undefined, + [ALERT_SERVICE_RISK_SCORE_CALCULATED_SCORE_NORM]: undefined, ...data, }, }); diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/enrichment_by_type/asset_criticality.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/enrichment_by_type/asset_criticality.ts index e2bd3319062ae..f6cd2dedb718a 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/enrichment_by_type/asset_criticality.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/enrichment_by_type/asset_criticality.ts @@ -8,6 +8,7 @@ import { cloneDeep } from 'lodash'; import { ALERT_HOST_CRITICALITY, + ALERT_SERVICE_CRITICALITY, ALERT_USER_CRITICALITY, } from '../../../../../../../common/field_maps/field_names'; import { createSingleFieldMatchEnrichment } from '../create_single_field_match_enrichment'; @@ -29,7 +30,10 @@ const getExtraFiltersForEnrichment = (field: string) => [ const createEnrichmentFactoryFunction = ( - alertField: typeof ALERT_HOST_CRITICALITY | typeof ALERT_USER_CRITICALITY + alertField: + | typeof ALERT_HOST_CRITICALITY + | typeof ALERT_USER_CRITICALITY + | typeof ALERT_SERVICE_CRITICALITY ): CreateEnrichmentFunction => (enrichment) => (event) => { @@ -88,3 +92,25 @@ export const createUserAssetCriticalityEnrichments: CreateCriticalityEnrichment createEnrichmentFunction: createEnrichmentFactoryFunction(ALERT_USER_CRITICALITY), }); }; + +export const createServiceAssetCriticalityEnrichments: CreateCriticalityEnrichment = async ({ + services, + logger, + events, + spaceId, +}) => { + return createSingleFieldMatchEnrichment({ + name: 'Service Asset Criticality', + index: [getAssetCriticalityIndex(spaceId)], + services, + logger, + events, + mappingField: { + eventField: 'service.name', + enrichmentField: 'id_value', + }, + enrichmentResponseFields, + extraFilters: getExtraFiltersForEnrichment('service.name'), + createEnrichmentFunction: createEnrichmentFactoryFunction(ALERT_SERVICE_CRITICALITY), + }); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/enrichment_by_type/service_risk.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/enrichment_by_type/service_risk.ts new file mode 100644 index 0000000000000..52d29ad0b6e81 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/enrichment_by_type/service_risk.ts @@ -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 { set } from '@kbn/safer-lodash-set'; +import { cloneDeep } from 'lodash'; +import { + ALERT_SERVICE_RISK_SCORE_CALCULATED_LEVEL, + ALERT_SERVICE_RISK_SCORE_CALCULATED_SCORE_NORM, +} from '../../../../../../../common/field_maps/field_names'; +import { getRiskIndex } from '../../../../../../../common/search_strategy/security_solution/risk_score/common'; +import { RiskScoreFields } from '../../../../../../../common/search_strategy/security_solution/risk_score/all'; +import { createSingleFieldMatchEnrichment } from '../create_single_field_match_enrichment'; +import type { CreateRiskEnrichment } from '../types'; +import { getFieldValue } from '../utils/events'; + +export const createServiceRiskEnrichments: CreateRiskEnrichment = async ({ + services, + logger, + events, + spaceId, +}) => { + return createSingleFieldMatchEnrichment({ + name: 'Service Risk', + index: [getRiskIndex(spaceId, true)], + services, + logger, + events, + mappingField: { + eventField: 'service.name', + enrichmentField: RiskScoreFields.serviceName, + }, + enrichmentResponseFields: [ + RiskScoreFields.serviceName, + RiskScoreFields.serviceRisk, + RiskScoreFields.serviceRiskScore, + ], + createEnrichmentFunction: (enrichment) => (event) => { + const riskLevel = getFieldValue(enrichment, RiskScoreFields.serviceRisk); + const riskScore = getFieldValue(enrichment, RiskScoreFields.serviceRiskScore); + if (!riskLevel && !riskScore) { + return event; + } + const newEvent = cloneDeep(event); + if (riskLevel) { + set(newEvent, `_source.${ALERT_SERVICE_RISK_SCORE_CALCULATED_LEVEL}`, riskLevel); + } + if (riskScore) { + set(newEvent, `_source.${ALERT_SERVICE_RISK_SCORE_CALCULATED_SCORE_NORM}`, riskScore); + } + return newEvent; + }, + }); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/index.test.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/index.test.ts index 8aca14228d665..4d971f142017a 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/index.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/index.test.ts @@ -60,6 +60,23 @@ const userEnrichmentResponse = [ }, ]; +const serviceEnrichmentResponse = [ + { + fields: { + 'service.name': ['service name 1'], + 'service.risk.calculated_level': ['Moderate'], + 'service.risk.calculated_score_norm': [50], + }, + }, + { + fields: { + 'service.name': ['service name 2'], + 'service.risk.calculated_level': ['Critical'], + 'service.risk.calculated_score_norm': [90], + }, + }, +]; + const assetCriticalityUserResponse = [ { fields: { @@ -84,6 +101,15 @@ const assetCriticalityHostResponse = [ }, ]; +const assetCriticalityServiceResponse = [ + { + fields: { + id_value: ['service name 1'], + criticality_level: ['high'], + }, + }, +]; + describe('enrichEvents', () => { let ruleExecutionLogger: ReturnType; let alertServices: RuleExecutorServicesMock; @@ -132,7 +158,8 @@ describe('enrichEvents', () => { it('return enriched events with risk score', async () => { mockSearchEnrichments .mockReturnValueOnce(hostEnrichmentResponse) - .mockReturnValueOnce(userEnrichmentResponse); + .mockReturnValueOnce(userEnrichmentResponse) + .mockReturnValueOnce(serviceEnrichmentResponse); mockIsIndexExist.mockImplementation(() => true); const enrichedEvents = await enrichEvents({ @@ -142,8 +169,9 @@ describe('enrichEvents', () => { createAlert('1', { ...createEntity('host', 'host name 1'), ...createEntity('user', 'user name 1'), + ...createEntity('service', 'service name 1'), }), - createAlert('2', createEntity('user', 'user name 2')), + createAlert('2', createEntity('service', 'service name 2')), ], spaceId: 'default', }); @@ -164,10 +192,17 @@ describe('enrichEvents', () => { calculated_score_norm: 50, }, }, + service: { + name: 'service name 1', + risk: { + calculated_level: 'Moderate', + calculated_score_norm: 50, + }, + }, }), createAlert('2', { - user: { - name: 'user name 2', + service: { + name: 'service name 2', risk: { calculated_level: 'Critical', calculated_score_norm: 90, @@ -180,11 +215,11 @@ describe('enrichEvents', () => { it('return enriched events with asset criticality', async () => { mockSearchEnrichments .mockReturnValueOnce(assetCriticalityUserResponse) - .mockReturnValueOnce(assetCriticalityHostResponse); + .mockReturnValueOnce(assetCriticalityHostResponse) + .mockReturnValueOnce(assetCriticalityServiceResponse); // disable risk score enrichments mockIsIndexExist.mockImplementationOnce(() => false); - mockIsIndexExist.mockImplementationOnce(() => false); // enable for asset criticality mockIsIndexExist.mockImplementation(() => true); @@ -195,6 +230,7 @@ describe('enrichEvents', () => { createAlert('1', { ...createEntity('host', 'host name 1'), ...createEntity('user', 'user name 1'), + ...createEntity('service', 'service name 1'), }), createAlert('2', createEntity('host', 'user name 1')), ], @@ -206,9 +242,10 @@ describe('enrichEvents', () => { createAlert('1', { ...createEntity('user', 'user name 1'), ...createEntity('host', 'host name 1'), - + ...createEntity('service', 'service name 1'), 'host.asset.criticality': 'low', 'user.asset.criticality': 'important', + 'service.asset.criticality': 'high', }), createAlert('2', { ...createEntity('host', 'user name 1'), @@ -223,7 +260,6 @@ describe('enrichEvents', () => { }) .mockImplementationOnce(() => userEnrichmentResponse); mockIsIndexExist.mockImplementation(() => true); - mockIsIndexExist.mockImplementation(() => true); const enrichedEvents = await enrichEvents({ logger: ruleExecutionLogger, diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/index.ts index 211162d6c7459..1fcef5343ebed 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/index.ts @@ -11,6 +11,7 @@ import { createUserRiskEnrichments } from './enrichment_by_type/user_risk'; import { createHostAssetCriticalityEnrichments, + createServiceAssetCriticalityEnrichments, createUserAssetCriticalityEnrichments, } from './enrichment_by_type/asset_criticality'; import { getAssetCriticalityIndex } from '../../../../../../common/entity_analytics/asset_criticality'; @@ -22,6 +23,7 @@ import type { import { applyEnrichmentsToEvents } from './utils/transforms'; import { isIndexExist } from './utils/is_index_exist'; import { getRiskIndex } from '../../../../../../common/search_strategy'; +import { createServiceRiskEnrichments } from './enrichment_by_type/service_risk'; export const enrichEvents: EnrichEventsFunction = async ({ services, @@ -35,18 +37,12 @@ export const enrichEvents: EnrichEventsFunction = async ({ logger.debug('Alert enrichments started'); - const [isHostRiskScoreIndexExist, isUserRiskScoreIndexExist] = await Promise.all([ - isIndexExist({ - services, - index: getRiskIndex(spaceId, true), - }), - isIndexExist({ - services, - index: getRiskIndex(spaceId, true), - }), - ]); + const isRiskScoreIndexExist = await isIndexExist({ + services, + index: getRiskIndex(spaceId, true), + }); - if (isHostRiskScoreIndexExist) { + if (isRiskScoreIndexExist) { enrichments.push( createHostRiskEnrichments({ services, @@ -55,9 +51,7 @@ export const enrichEvents: EnrichEventsFunction = async ({ spaceId, }) ); - } - if (isUserRiskScoreIndexExist) { enrichments.push( createUserRiskEnrichments({ services, @@ -66,6 +60,15 @@ export const enrichEvents: EnrichEventsFunction = async ({ spaceId, }) ); + + enrichments.push( + createServiceRiskEnrichments({ + services, + logger, + events, + spaceId, + }) + ); } const assetCriticalityIndexExist = await isIndexExist({ @@ -89,6 +92,14 @@ export const enrichEvents: EnrichEventsFunction = async ({ spaceId, }) ); + enrichments.push( + createServiceAssetCriticalityEnrichments({ + services, + logger, + events, + spaceId, + }) + ); } const allEnrichmentsResults = await Promise.allSettled(enrichments); diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.test.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.test.ts index e9cc5273b58a6..ca54ce647940a 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.test.ts @@ -43,7 +43,7 @@ describe('AssetCriticalityDataClient', () => { index: '.asset-criticality.asset-criticality-default', mappings: { _meta: { - version: 2, + version: 3, }, dynamic: 'strict', properties: { @@ -56,6 +56,13 @@ describe('AssetCriticalityDataClient', () => { criticality_level: { type: 'keyword', }, + event: { + properties: { + ingested: { + type: 'date', + }, + }, + }, '@timestamp': { type: 'date', ignore_malformed: false, @@ -114,6 +121,9 @@ describe('AssetCriticalityDataClient', () => { }, }, }, + settings: { + default_pipeline: 'entity_analytics_create_eventIngest_from_timestamp-pipeline-default', + }, }, }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.ts index 14b4fb64fbd33..0cc028fc32ec2 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.ts @@ -26,6 +26,10 @@ import { import { AssetCriticalityAuditActions } from './audit'; import { AUDIT_CATEGORY, AUDIT_OUTCOME, AUDIT_TYPE } from '../audit'; import { getImplicitEntityFields } from './helpers'; +import { + getIngestPipelineName, + createEventIngestedFromTimestamp, +} from '../utils/create_ingest_pipeline'; interface AssetCriticalityClientOpts { logger: Logger; @@ -62,6 +66,7 @@ export class AssetCriticalityDataClient { * Initialize asset criticality resources. */ public async init() { + await createEventIngestedFromTimestamp(this.options.esClient, this.options.namespace); await this.createOrUpdateIndex(); this.options.auditLogger?.log({ @@ -90,6 +95,9 @@ export class AssetCriticalityDataClient { version: ASSET_CRITICALITY_MAPPINGS_VERSIONS, }, }, + settings: { + default_pipeline: getIngestPipelineName(this.options.namespace), + }, }, }); } diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_migration_client.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_migration_client.ts index dfa3b3fdb6325..dc79a467f1439 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_migration_client.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_migration_client.ts @@ -95,4 +95,36 @@ export class AssetCriticalityMigrationClient { } ); }; + + public copyTimestampToEventIngestedForAssetCriticality = (abortSignal?: AbortSignal) => { + return this.options.esClient.updateByQuery( + { + index: this.assetCriticalityDataClient.getIndex(), + conflicts: 'proceed', + ignore_unavailable: true, + allow_no_indices: true, + body: { + query: { + bool: { + must_not: { + exists: { + field: 'event.ingested', + }, + }, + }, + }, + script: { + source: 'ctx._source.event.ingested = ctx._source.@timestamp', + lang: 'painless', + }, + }, + }, + { + requestTimeout: '5m', + retryOnTimeout: true, + maxRetries: 2, + signal: abortSignal, + } + ); + }; } diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/constants.test.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/constants.test.ts index deb2a1d5d8d4c..c22057ea92d48 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/constants.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/constants.test.ts @@ -9,7 +9,7 @@ import { ASSET_CRITICALITY_MAPPINGS_VERSIONS, assetCriticalityFieldMap } from '. describe('asset criticality - constants', () => { it("please bump 'ASSET_CRITICALITY_MAPPINGS_VERSIONS' when mappings change", () => { - expect(ASSET_CRITICALITY_MAPPINGS_VERSIONS).toEqual(2); + expect(ASSET_CRITICALITY_MAPPINGS_VERSIONS).toEqual(3); expect(assetCriticalityFieldMap).toMatchInlineSnapshot(` Object { "@timestamp": Object { @@ -27,6 +27,11 @@ describe('asset criticality - constants', () => { "required": false, "type": "keyword", }, + "event.ingested": Object { + "array": false, + "required": false, + "type": "date", + }, "host.asset.criticality": Object { "array": false, "required": false, diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/constants.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/constants.ts index f536e7e649086..3066b13522962 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/constants.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/asset_criticality/constants.ts @@ -17,7 +17,7 @@ const assetCriticalityMapping = { }; // Upgrade this value to force a mappings update on the next Kibana startup -export const ASSET_CRITICALITY_MAPPINGS_VERSIONS = 2; +export const ASSET_CRITICALITY_MAPPINGS_VERSIONS = 3; export const assetCriticalityFieldMap: FieldMap = { '@timestamp': { @@ -58,6 +58,11 @@ export const assetCriticalityFieldMap: FieldMap = { required: false, }, 'user.asset.criticality': assetCriticalityMapping, + 'event.ingested': { + type: 'date', + array: false, + required: false, + }, 'service.name': { type: 'keyword', array: false, diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/elasticsearch_assets/enrich_policy.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/elasticsearch_assets/enrich_policy.ts index 35a7fc40fc58d..9aa3dd8825eb5 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/elasticsearch_assets/enrich_policy.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/elasticsearch_assets/enrich_policy.ts @@ -32,6 +32,10 @@ export const createFieldRetentionEnrichPolicy = async ({ description: EntityEngineInstallationDescriptor; options: { namespace: string }; }) => { + const enrichFields = description.dynamic + ? ['*'] + : description.fields.map(({ destination }) => destination); + return esClient.enrich.putPolicy({ name: getFieldRetentionEnrichPolicyName({ namespace: options.namespace, @@ -41,7 +45,7 @@ export const createFieldRetentionEnrichPolicy = async ({ match: { indices: getEntitiesIndexName(description.entityType, options.namespace), match_field: description.identityField, - enrich_fields: description.fields.map(({ destination }) => destination), + enrich_fields: enrichFields, }, }); }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/elasticsearch_assets/ingest_pipeline.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/elasticsearch_assets/ingest_pipeline.ts index c6b2a5902ec7f..1017d04120908 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/elasticsearch_assets/ingest_pipeline.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/elasticsearch_assets/ingest_pipeline.ts @@ -20,6 +20,7 @@ import { getFieldRetentionEnrichPolicyName } from './enrich_policy'; import { fieldOperatorToIngestProcessor } from '../field_retention'; import type { EntityEngineInstallationDescriptor } from '../installation/types'; +import { dynamicNewestRetentionSteps } from '../field_retention/dynamic_retention'; const getPlatformPipelineId = (descriptionId: string) => { return `${descriptionId}-latest@platform`; @@ -56,13 +57,6 @@ const buildIngestPipeline = ({ }); const processors = [ - { - enrich: { - policy_name: enrichPolicyName, - field: description.identityField, - target_field: ENRICH_FIELD, - }, - }, { set: { field: '@timestamp', @@ -75,12 +69,38 @@ const buildIngestPipeline = ({ value: `{{${description.identityField}}}`, }, }, + ...(debugMode + ? [ + { + set: { + field: 'debug.collected', + value: '{{collected.metadata}}', + }, + }, + { + set: { + field: 'debug._source', + value: '{{_source}}', + }, + }, + ] + : []), + { + enrich: { + policy_name: enrichPolicyName, + field: description.identityField, + target_field: ENRICH_FIELD, + }, + }, ...getDotExpanderSteps(allEntityFields), ...description.fields.map((field) => fieldOperatorToIngestProcessor(field, { enrichField: ENRICH_FIELD }) ), ...getRemoveEmptyFieldSteps([...allEntityFields, 'asset', `${description.entityType}.risk`]), removeEntityDefinitionFieldsStep(), + ...(description.dynamic + ? [dynamicNewestRetentionSteps(description.fields.map((field) => field.destination))] + : []), ...(!debugMode ? [ { @@ -93,12 +113,9 @@ const buildIngestPipeline = ({ : []), ]; - const extraSteps = - (typeof description.pipeline === 'function' - ? description.pipeline(processors) - : description.pipeline) ?? []; - - return [...(debugMode ? [debugDeepCopyContextStep()] : []), ...processors, ...extraSteps]; + return typeof description.pipeline === 'function' + ? description.pipeline(processors) + : [...(debugMode ? [debugDeepCopyContextStep()] : []), ...processors]; }; // developing the pipeline is a bit tricky, so we have a debug mode diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_definitions/entity_descriptions/service.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_definitions/entity_descriptions/service.ts index 86c5091d2844a..4f3f85e11a061 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_definitions/entity_descriptions/service.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_definitions/entity_descriptions/service.ts @@ -6,6 +6,7 @@ */ import type { EntityDescription } from '../types'; +import { getCommonFieldDescriptions } from './common'; import { collectValues as collect, newestValue } from './field_utils'; export const SERVICE_DEFINITION_VERSION = '1.0.0'; @@ -25,8 +26,10 @@ export const serviceEntityEngineDescription: EntityDescription = { collect({ source: 'service.id' }), collect({ source: 'service.node.name' }), collect({ source: 'service.node.roles' }), + collect({ source: 'service.node.role' }), newestValue({ source: 'service.state' }), collect({ source: 'service.type' }), newestValue({ source: 'service.version' }), + ...getCommonFieldDescriptions('service'), ], }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_definitions/entity_descriptions/universal.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_definitions/entity_descriptions/universal.ts index d4e0997ee4f93..e0dd82f0b330d 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_definitions/entity_descriptions/universal.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_definitions/entity_descriptions/universal.ts @@ -5,13 +5,14 @@ * 2.0. */ +import type { IngestProcessorContainer } from '@elastic/elasticsearch/lib/api/types'; import type { EntityDescription } from '../types'; -import { collectValues as collect } from './field_utils'; +import { collectValues } from './field_utils'; export const UNIVERSAL_DEFINITION_VERSION = '1.0.0'; export const UNIVERSAL_IDENTITY_FIELD = 'related.entity'; -const entityMetadataExtractorProcessor = { +export const entityMetadataExtractorProcessor = { script: { tag: 'entity_metadata_extractor', on_failure: [ @@ -25,20 +26,42 @@ const entityMetadataExtractorProcessor = { ], lang: 'painless', source: /* java */ ` - Map merged = ctx; - def id = ctx.entity.id; + // Array, boolean, integer, ip, bytes, anything that is not a map, is a leaf field + void overwriteLeafFields(Object toBeOverwritten, Object toOverwrite) { + if (!(toBeOverwritten instanceof Map)) { + // We can't override anything that isn't a map + return; + } + if (toOverwrite instanceof Map) { + Map mapToBeOverwritten = (Map) toBeOverwritten; + for (entryToOverwrite in ((Map) toOverwrite).entrySet()) { + String keyToOverwrite = entryToOverwrite.getKey(); + Object valueToOverwrite = entryToOverwrite.getValue(); + + if (valueToOverwrite instanceof Map) { + // If no initial value, we just put everything we have to overwrite + if (mapToBeOverwritten.get(keyToOverwrite) == null) { + mapToBeOverwritten.put(keyToOverwrite, valueToOverwrite) + } else { + overwriteLeafFields(mapToBeOverwritten.get(keyToOverwrite), valueToOverwrite); + } + } else { + mapToBeOverwritten.put(keyToOverwrite, valueToOverwrite) + } + } + } + } + def id = ctx.entity.id; + Map merged = ctx; for (meta in ctx.collected.metadata) { Object json = Processors.json(meta); - if (((Map)json)[id] == null) { continue; } - for (entry in ((Map)json)[id].entrySet()) { - String key = entry.getKey(); - Object value = entry.getValue(); - merged.put(key, value); + if (((Map)json)[id] != null) { + overwriteLeafFields(merged, ((Map)json)[id]); } } @@ -52,9 +75,22 @@ export const universalEntityEngineDescription: EntityDescription = { version: UNIVERSAL_DEFINITION_VERSION, entityType: 'universal', identityField: UNIVERSAL_IDENTITY_FIELD, - fields: [collect({ source: 'entities.keyword', destination: 'collected.metadata' })], + fields: [collectValues({ source: 'entities.keyword', destination: 'collected.metadata' })], settings: { timestampField: 'event.ingested', }, - pipeline: [entityMetadataExtractorProcessor], + pipeline: (processors: IngestProcessorContainer[]) => { + const index = processors.findIndex((p) => Boolean(p.enrich)); + + if (index === -1) { + throw new Error('Enrich processor not found'); + } + + const init = processors.slice(0, index); + const tail = processors.slice(index); + const pipe = [...init, entityMetadataExtractorProcessor, ...tail]; + + return pipe; + }, + dynamic: true, }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_definitions/entity_manager_conversion.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_definitions/entity_manager_conversion.ts index acc69c9bf9d33..3c1ba8621051c 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_definitions/entity_manager_conversion.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_definitions/entity_manager_conversion.ts @@ -28,6 +28,7 @@ export const convertToEntityManagerDefinition = ( timestampField: description.settings.timestampField, lookbackPeriod: description.settings.lookbackPeriod, settings: { + syncField: description.settings.timestampField, syncDelay: description.settings.syncDelay, frequency: description.settings.frequency, }, diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_definitions/types.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_definitions/types.ts index e271c29e1d186..d7529bcd57f1f 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_definitions/types.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_definitions/types.ts @@ -22,6 +22,7 @@ export type EntityDescription = PickPartial< | 'indexPatterns' | 'indexMappings' | 'settings' - | 'pipeline', - 'indexPatterns' | 'indexMappings' | 'settings' | 'pipeline' + | 'pipeline' + | 'dynamic', + 'indexPatterns' | 'indexMappings' | 'settings' | 'pipeline' | 'dynamic' >; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_store_data_client.test.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_store_data_client.test.ts index 4ba9729c717e0..2abbf9a79872e 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_store_data_client.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_store_data_client.test.ts @@ -36,6 +36,7 @@ const definition: EntityDefinition = convertToEntityManagerDefinition( timestampField: '@timestamp', lookbackPeriod: '24h', }, + dynamic: false, }, { namespace: 'test', filter: '' } ); @@ -270,7 +271,7 @@ describe('EntityStoreDataClient', () => { installed: true, }, { - id: 'security_host_test', + id: 'indexTemplates_id', installed: true, resource: 'index_template', }, diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_store_data_client.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_store_data_client.ts index 3be25dd55a6cd..e0b1f7262a11e 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_store_data_client.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_store_data_client.ts @@ -505,8 +505,8 @@ export class EntityStoreDataClient { resource: EngineComponentResourceEnum.ingest_pipeline, ...pipeline, })), - ...definition.state.components.indexTemplates.map(({ installed }) => ({ - id, + ...definition.state.components.indexTemplates.map(({ installed, id: templateId }) => ({ + id: templateId, installed, resource: EngineComponentResourceEnum.index_template, })), diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/field_retention/dynamic_retention.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/field_retention/dynamic_retention.ts new file mode 100644 index 0000000000000..914463f2d30e3 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/field_retention/dynamic_retention.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. + */ + +export const dynamicNewestRetentionSteps = (ignoreFields: string[]) => { + const staticFields = ignoreFields.map((field) => `"${field}"`).join(','); + + const painless = /* java */ ` + Map mergeFields(Map latest, Map historical, Set staticFields) { + for (entry in historical.entrySet()) { + String key = entry.getKey(); + if (staticFields.contains(key)) { + continue; + } + + def historicalValue = entry.getValue(); + if (latest.containsKey(key)) { + def latestValue = latest.get(key); + if (latestValue instanceof Map && historicalValue instanceof Map) { + latest.put(key, mergeFields(latestValue, historicalValue, staticFields)); + } + } else { + latest.put(key, historicalValue); + } + } + return latest; + } + + Set staticFields = new HashSet([${staticFields}]); + if (ctx.historical != null && ctx.historical instanceof Map) { + ctx = mergeFields(ctx, ctx.historical, staticFields); + } + `; + return { + script: { + source: painless, + lang: 'painless', + }, + }; +}; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/installation/engine_description.test.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/installation/engine_description.test.ts index 81290e832978c..480dadf676f3c 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/installation/engine_description.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/installation/engine_description.test.ts @@ -125,6 +125,7 @@ describe('getUnitedEntityDefinition', () => { "settings": Object { "frequency": "60s", "syncDelay": "60s", + "syncField": "@timestamp", }, "timestampField": "@timestamp", }, @@ -363,6 +364,7 @@ describe('getUnitedEntityDefinition', () => { "settings": Object { "frequency": "60s", "syncDelay": "60s", + "syncField": "@timestamp", }, "timestampField": "@timestamp", }, @@ -534,9 +536,21 @@ describe('getUnitedEntityDefinition', () => { "service.node.name": Object { "type": "keyword", }, + "service.node.role": Object { + "type": "keyword", + }, "service.node.roles": Object { "type": "keyword", }, + "service.risk.calculated_level": Object { + "type": "keyword", + }, + "service.risk.calculated_score": Object { + "type": "float", + }, + "service.risk.calculated_score_norm": Object { + "type": "float", + }, "service.state": Object { "type": "keyword", }, @@ -574,6 +588,7 @@ describe('getUnitedEntityDefinition', () => { "settings": Object { "frequency": "60s", "syncDelay": "60s", + "syncField": "@timestamp", }, "timestampField": "@timestamp", }, @@ -627,6 +642,14 @@ describe('getUnitedEntityDefinition', () => { "destination": "service.node.roles", "source": "service.node.roles", }, + Object { + "aggregation": Object { + "limit": 10, + "type": "terms", + }, + "destination": "service.node.role", + "source": "service.node.role", + }, Object { "aggregation": Object { "sort": Object { @@ -655,6 +678,56 @@ describe('getUnitedEntityDefinition', () => { "destination": "service.version", "source": "service.version", }, + Object { + "aggregation": Object { + "sort": Object { + "@timestamp": "asc", + }, + "type": "top_value", + }, + "destination": "entity.source", + "source": "_index", + }, + Object { + "aggregation": Object { + "sort": Object { + "@timestamp": "desc", + }, + "type": "top_value", + }, + "destination": "asset.criticality", + "source": "asset.criticality", + }, + Object { + "aggregation": Object { + "sort": Object { + "@timestamp": "desc", + }, + "type": "top_value", + }, + "destination": "service.risk.calculated_level", + "source": "service.risk.calculated_level", + }, + Object { + "aggregation": Object { + "sort": Object { + "@timestamp": "desc", + }, + "type": "top_value", + }, + "destination": "service.risk.calculated_score", + "source": "service.risk.calculated_score", + }, + Object { + "aggregation": Object { + "sort": Object { + "@timestamp": "desc", + }, + "type": "top_value", + }, + "destination": "service.risk.calculated_score_norm", + "source": "service.risk.calculated_score_norm", + }, ], "name": "Security 'service' Entity Store Definition", "type": "service", diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/installation/engine_description.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/installation/engine_description.ts index b380dba9b8396..d60e09935bda9 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/installation/engine_description.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/installation/engine_description.ts @@ -69,6 +69,7 @@ export const createEngineDescription = (options: EngineDescriptionParams) => { update('settings', assign(settings)), updateIndexPatterns(indexPatterns), updateRetentionFields(fieldHistoryLength), + setDefaultDynamic, addIndexMappings ) as EntityEngineInstallationDescriptor; @@ -91,3 +92,5 @@ const updateRetentionFields = (fieldHistoryLength: number) => const addIndexMappings = (description: EntityEngineInstallationDescriptor) => set('indexMappings', generateIndexMappings(description), description); + +const setDefaultDynamic = update('dynamic', (dynamic = false) => dynamic); diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/installation/types.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/installation/types.ts index b68ce5faa1ac4..7ec798ca26fbf 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/installation/types.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/installation/types.ts @@ -20,7 +20,6 @@ export interface EntityEngineInstallationDescriptor { id: string; version: string; entityType: EntityType; - identityField: string; /** @@ -60,6 +59,14 @@ export interface EntityEngineInstallationDescriptor { pipeline: | IngestProcessorContainer[] | ((defaultProcessors: IngestProcessorContainer[]) => IngestProcessorContainer[]); + + /** + * Whether the extracted entity data is dynamic. + * If true, it means we don't know which fields will be extracted from the definition itself, and we need to apply field retention to all the incoming doc's fields. + * + * This is mainly used for the Asset Inventory use case. + */ + dynamic: boolean; } export type FieldDescription = EntityDefinitionMetadataElement & { diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/migrations/asset_criticality_copy_timestamp_to_event_ingested.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/migrations/asset_criticality_copy_timestamp_to_event_ingested.ts new file mode 100644 index 0000000000000..cffd417b907ce --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/migrations/asset_criticality_copy_timestamp_to_event_ingested.ts @@ -0,0 +1,98 @@ +/* + * 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 { EntityAnalyticsMigrationsParams } from '.'; +import { AssetCriticalityMigrationClient } from '../asset_criticality/asset_criticality_migration_client'; + +const TASK_TYPE = 'security-solution-ea-asset-criticality-copy-timestamp-to-event-ingested'; +const TASK_ID = `${TASK_TYPE}-task-id`; +const TASK_TIMEOUT = '15m'; +const TASK_SCOPE = ['securitySolution']; + +export const assetCrticalityCopyTimestampToEventIngested = async ({ + auditLogger, + taskManager, + logger, + getStartServices, +}: EntityAnalyticsMigrationsParams) => { + if (!taskManager) { + return; + } + + logger.debug(`Register task "${TASK_TYPE}"`); + + taskManager.registerTaskDefinitions({ + [TASK_TYPE]: { + title: `Copy Asset Criticality @timestamp value to events.ingested`, + timeout: TASK_TIMEOUT, + createTaskRunner: createMigrationTask({ auditLogger, logger, getStartServices }), + }, + }); + + const [_, depsStart] = await getStartServices(); + const taskManagerStart = depsStart.taskManager; + + if (taskManagerStart) { + logger.debug(`Task scheduled: "${TASK_TYPE}"`); + + const now = new Date(); + try { + await taskManagerStart.ensureScheduled({ + id: TASK_ID, + taskType: TASK_TYPE, + scheduledAt: now, + runAt: now, + scope: TASK_SCOPE, + params: {}, + state: {}, + }); + } catch (e) { + logger.error(`Error scheduling ${TASK_ID}, received ${e.message}`); + } + } +}; + +export const createMigrationTask = + ({ + getStartServices, + logger, + auditLogger, + }: Pick) => + () => { + let abortController: AbortController; + return { + run: async () => { + abortController = new AbortController(); + const [coreStart] = await getStartServices(); + const esClient = coreStart.elasticsearch.client.asInternalUser; + const assetCrticalityClient = new AssetCriticalityMigrationClient({ + esClient, + logger, + auditLogger, + }); + + const assetCriticalityResponse = + await assetCrticalityClient.copyTimestampToEventIngestedForAssetCriticality( + abortController.signal + ); + + const failures = assetCriticalityResponse.failures?.map((failure) => failure.cause); + const hasFailures = failures && failures?.length > 0; + + logger.info( + `Task "${TASK_TYPE}" finished. Updated documents: ${ + assetCriticalityResponse.updated + }, failures: ${hasFailures ? failures.join('\n') : 0}` + ); + }, + + cancel: async () => { + abortController.abort(); + logger.debug(`Task cancelled: "${TASK_TYPE}"`); + }, + }; + }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/migrations/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/migrations/index.ts index dac3099a0b3f8..498d9c954c206 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/migrations/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/migrations/index.ts @@ -9,6 +9,8 @@ import type { AuditLogger, Logger, StartServicesAccessor } from '@kbn/core/serve import type { TaskManagerSetupContract } from '@kbn/task-manager-plugin/server'; import type { StartPlugins } from '../../../plugin'; import { scheduleAssetCriticalityEcsCompliancyMigration } from '../asset_criticality/migrations/schedule_ecs_compliancy_migration'; +import { assetCrticalityCopyTimestampToEventIngested } from './asset_criticality_copy_timestamp_to_event_ingested'; +import { riskScoreCopyTimestampToEventIngested } from './risk_score_copy_timestamp_to_event_ingested'; import { updateAssetCriticalityMappings } from '../asset_criticality/migrations/update_asset_criticality_mappings'; import { updateRiskScoreMappings } from '../risk_engine/migrations/update_risk_score_mappings'; @@ -43,3 +45,21 @@ export const scheduleEntityAnalyticsMigration = async (params: EntityAnalyticsMi await scheduleAssetCriticalityEcsCompliancyMigration({ ...params, logger: scopedLogger }); await updateRiskScoreMappings({ ...params, logger: scopedLogger }); }; + +export const scheduleAssetCriticalityCopyTimestampToEventIngested = async ( + params: EntityAnalyticsMigrationsParams +) => { + const scopedLogger = params.logger.get( + 'entityAnalytics.assetCriticality.copyTimestampToEventIngested' + ); + + await assetCrticalityCopyTimestampToEventIngested({ ...params, logger: scopedLogger }); +}; + +export const scheduleRiskScoreCopyTimestampToEventIngested = async ( + params: EntityAnalyticsMigrationsParams +) => { + const scopedLogger = params.logger.get('entityAnalytics.riskScore.copyTimestampToEventIngested'); + + await riskScoreCopyTimestampToEventIngested({ ...params, logger: scopedLogger }); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/migrations/risk_score_copy_timestamp_to_event_ingested.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/migrations/risk_score_copy_timestamp_to_event_ingested.ts new file mode 100644 index 0000000000000..3fb5eecae237b --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/migrations/risk_score_copy_timestamp_to_event_ingested.ts @@ -0,0 +1,101 @@ +/* + * 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 { EntityAnalyticsMigrationsParams } from '.'; +import { RiskScoreDataClient } from '../risk_score/risk_score_data_client'; +import { buildScopedInternalSavedObjectsClientUnsafe } from '../risk_score/tasks/helpers'; + +const TASK_TYPE = 'security-solution-ea-risk-score-copy-timestamp-to-event-ingested'; +const TASK_ID = `${TASK_TYPE}-task-id`; +const TASK_TIMEOUT = '15m'; +const TASK_SCOPE = ['securitySolution']; + +export const riskScoreCopyTimestampToEventIngested = async ({ + auditLogger, + taskManager, + logger, + getStartServices, +}: EntityAnalyticsMigrationsParams) => { + if (!taskManager) { + return; + } + + logger.debug(`Register task "${TASK_TYPE}"`); + + taskManager.registerTaskDefinitions({ + [TASK_TYPE]: { + title: `Copy Risk Score @timestamp value to events.ingested`, + timeout: TASK_TIMEOUT, + createTaskRunner: createMigrationTask({ auditLogger, logger, getStartServices }), + }, + }); + + const [_, depsStart] = await getStartServices(); + const taskManagerStart = depsStart.taskManager; + + if (taskManagerStart) { + logger.debug(`Task scheduled: "${TASK_TYPE}"`); + + const now = new Date(); + try { + await taskManagerStart.ensureScheduled({ + id: TASK_ID, + taskType: TASK_TYPE, + scheduledAt: now, + runAt: now, + scope: TASK_SCOPE, + params: {}, + state: {}, + }); + } catch (e) { + logger.error(`Error scheduling ${TASK_ID}, received ${e.message}`); + } + } +}; + +export const createMigrationTask = + ({ + getStartServices, + logger, + auditLogger, + }: Pick) => + () => { + let abortController: AbortController; + return { + run: async () => { + abortController = new AbortController(); + const [coreStart] = await getStartServices(); + const esClient = coreStart.elasticsearch.client.asInternalUser; + const soClient = buildScopedInternalSavedObjectsClientUnsafe({ coreStart, namespace: '*' }); + + const riskScoreClient = new RiskScoreDataClient({ + esClient, + logger, + auditLogger, + namespace: '*', + soClient, + kibanaVersion: '*', + }); + const riskScoreResponse = await riskScoreClient.copyTimestampToEventIngestedForRiskScore( + abortController.signal + ); + const failures = riskScoreResponse.failures?.map((failure) => failure.cause); + const hasFailures = failures && failures?.length > 0; + + logger.info( + `Task "${TASK_TYPE}" finished. Updated documents: ${ + riskScoreResponse.updated + }, failures: ${hasFailures ? failures.join('\n') : 0}` + ); + }, + + cancel: async () => { + abortController.abort(); + logger.debug(`Task cancelled: "${TASK_TYPE}"`); + }, + }; + }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_engine/utils/saved_object_configuration.test.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_engine/utils/saved_object_configuration.test.ts index 60e9f44965a7c..3ce478af30c6a 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_engine/utils/saved_object_configuration.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_engine/utils/saved_object_configuration.test.ts @@ -13,7 +13,7 @@ describe('#getDefaultRiskEngineConfiguration', () => { const namespace = 'default'; const config = getDefaultRiskEngineConfiguration({ namespace }); - expect(config._meta.mappingsVersion).toEqual(2); + expect(config._meta.mappingsVersion).toEqual(3); expect(riskScoreFieldMap).toMatchInlineSnapshot(` Object { "@timestamp": Object { @@ -21,6 +21,11 @@ describe('#getDefaultRiskEngineConfiguration', () => { "required": false, "type": "date", }, + "event.ingested": Object { + "array": false, + "required": false, + "type": "date", + }, "host.name": Object { "array": false, "required": false, diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_engine/utils/saved_object_configuration.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_engine/utils/saved_object_configuration.ts index 3af27649f3d5e..e9b7560433953 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_engine/utils/saved_object_configuration.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_engine/utils/saved_object_configuration.ts @@ -28,7 +28,7 @@ export const getDefaultRiskEngineConfiguration = ({ range: { start: 'now-30d', end: 'now' }, _meta: { // Upgrade this property when changing mappings - mappingsVersion: 2, + mappingsVersion: 3, }, }); diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/__snapshots__/risk_score_data_client.test.ts.snap b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/__snapshots__/risk_score_data_client.test.ts.snap index 922ae18a4dfc7..6e48a94640cb5 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/__snapshots__/risk_score_data_client.test.ts.snap +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/__snapshots__/risk_score_data_client.test.ts.snap @@ -9,6 +9,13 @@ Object { "ignore_malformed": false, "type": "date", }, + "event": Object { + "properties": Object { + "ingested": Object { + "type": "date", + }, + }, + }, "host": Object { "properties": Object { "name": Object { diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/configurations.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/configurations.ts index d6f5983ca632b..962d6d5002dc8 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/configurations.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/configurations.ts @@ -102,6 +102,11 @@ export const riskScoreFieldMap: FieldMap = { array: false, required: false, }, + 'event.ingested': { + type: 'date', + array: false, + required: false, + }, 'host.name': { type: 'keyword', array: false, diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_score_data_client.test.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_score_data_client.test.ts index 1e285e27c4fe7..029179043957d 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_score_data_client.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_score_data_client.test.ts @@ -181,14 +181,12 @@ const assertIndexTemplate = (namespace: string) => { expect(createOrUpdateIndexTemplate).toHaveBeenCalledWith({ logger, esClient, - template: { + template: expect.objectContaining({ name: `.risk-score.risk-score-${namespace}-index-template`, - body: expect.objectContaining({ - data_stream: { hidden: true }, - index_patterns: [`risk-score.risk-score-${namespace}`], - composed_of: [`.risk-score-mappings-${namespace}`], - }), - }, + data_stream: { hidden: true }, + index_patterns: [`risk-score.risk-score-${namespace}`], + composed_of: [`.risk-score-mappings-${namespace}`], + }), }); }; @@ -210,7 +208,202 @@ const assertIndex = (namespace: string) => { esClient, options: { index: `risk-score.risk-score-latest-${namespace}`, - mappings: expect.any(Object), + mappings: { + dynamic: false, + properties: { + '@timestamp': { + ignore_malformed: false, + type: 'date', + }, + event: { + properties: { + ingested: { + type: 'date', + }, + }, + }, + host: { + properties: { + name: { + type: 'keyword', + }, + risk: { + properties: { + calculated_level: { + type: 'keyword', + }, + calculated_score: { + type: 'float', + }, + calculated_score_norm: { + type: 'float', + }, + category_1_count: { + type: 'long', + }, + category_1_score: { + type: 'float', + }, + id_field: { + type: 'keyword', + }, + id_value: { + type: 'keyword', + }, + notes: { + type: 'keyword', + }, + inputs: { + properties: { + id: { + type: 'keyword', + }, + index: { + type: 'keyword', + }, + category: { + type: 'keyword', + }, + description: { + type: 'keyword', + }, + risk_score: { + type: 'float', + }, + timestamp: { + type: 'date', + }, + }, + type: 'object', + }, + }, + type: 'object', + }, + }, + }, + service: { + properties: { + name: { + type: 'keyword', + }, + risk: { + properties: { + calculated_level: { + type: 'keyword', + }, + calculated_score: { + type: 'float', + }, + calculated_score_norm: { + type: 'float', + }, + category_1_count: { + type: 'long', + }, + category_1_score: { + type: 'float', + }, + id_field: { + type: 'keyword', + }, + id_value: { + type: 'keyword', + }, + inputs: { + properties: { + category: { + type: 'keyword', + }, + description: { + type: 'keyword', + }, + id: { + type: 'keyword', + }, + index: { + type: 'keyword', + }, + risk_score: { + type: 'float', + }, + timestamp: { + type: 'date', + }, + }, + type: 'object', + }, + notes: { + type: 'keyword', + }, + }, + type: 'object', + }, + }, + }, + user: { + properties: { + name: { + type: 'keyword', + }, + risk: { + properties: { + calculated_level: { + type: 'keyword', + }, + calculated_score: { + type: 'float', + }, + calculated_score_norm: { + type: 'float', + }, + category_1_count: { + type: 'long', + }, + category_1_score: { + type: 'float', + }, + id_field: { + type: 'keyword', + }, + id_value: { + type: 'keyword', + }, + notes: { + type: 'keyword', + }, + inputs: { + properties: { + id: { + type: 'keyword', + }, + index: { + type: 'keyword', + }, + category: { + type: 'keyword', + }, + description: { + type: 'keyword', + }, + risk_score: { + type: 'float', + }, + timestamp: { + type: 'date', + }, + }, + type: 'object', + }, + }, + type: 'object', + }, + }, + }, + }, + }, + settings: { + 'index.default_pipeline': `entity_analytics_create_eventIngest_from_timestamp-pipeline-${namespace}`, + }, }, }); }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_score_data_client.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_score_data_client.ts index 74391c6bc3c5b..69e2290af1476 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_score_data_client.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_score_data_client.ts @@ -45,6 +45,10 @@ import { createOrUpdateIndex } from '../utils/create_or_update_index'; import { retryTransientEsErrors } from '../utils/retry_transient_es_errors'; import { RiskScoreAuditActions } from './audit'; import { AUDIT_CATEGORY, AUDIT_OUTCOME, AUDIT_TYPE } from '../audit'; +import { + createEventIngestedFromTimestamp, + getIngestPipelineName, +} from '../utils/create_ingest_pipeline'; interface RiskScoringDataClientOpts { logger: Logger; @@ -100,6 +104,9 @@ export class RiskScoreDataClient { options: { index: getRiskScoreLatestIndex(this.options.namespace), mappings: mappingFromFieldMap(riskScoreFieldMap, false), + settings: { + 'index.default_pipeline': getIngestPipelineName(this.options.namespace), + }, }, }); }; @@ -130,9 +137,10 @@ export class RiskScoreDataClient { public async init() { const namespace = this.options.namespace; + const esClient = this.options.esClient; try { - const esClient = this.options.esClient; + await createEventIngestedFromTimestamp(esClient, namespace); const indexPatterns = getIndexPatternDataStream(namespace); @@ -161,22 +169,21 @@ export class RiskScoreDataClient { esClient, template: { name: indexPatterns.template, - body: { - data_stream: { hidden: true }, - index_patterns: [indexPatterns.alias], - composed_of: [nameSpaceAwareMappingsComponentName(namespace)], - template: { - lifecycle: {}, - settings: { - 'index.mapping.total_fields.limit': totalFieldsLimit, - }, - mappings: { - dynamic: false, - _meta: indexMetadata, - }, + data_stream: { hidden: true }, + index_patterns: [indexPatterns.alias], + composed_of: [nameSpaceAwareMappingsComponentName(namespace)], + template: { + lifecycle: {}, + settings: { + 'index.mapping.total_fields.limit': totalFieldsLimit, + 'index.default_pipeline': getIngestPipelineName(namespace), + }, + mappings: { + dynamic: false, + _meta: indexMetadata, }, - _meta: indexMetadata, }, + _meta: indexMetadata, }, }); @@ -340,6 +347,38 @@ export class RiskScoreDataClient { }); } + public copyTimestampToEventIngestedForRiskScore = (abortSignal?: AbortSignal) => { + return this.options.esClient.updateByQuery( + { + index: getRiskScoreLatestIndex(this.options.namespace), + conflicts: 'proceed', + ignore_unavailable: true, + allow_no_indices: true, + body: { + query: { + bool: { + must_not: { + exists: { + field: 'event.ingested', + }, + }, + }, + }, + script: { + source: 'ctx._source.event.ingested = ctx._source.@timestamp', + lang: 'painless', + }, + }, + }, + { + requestTimeout: '5m', + retryOnTimeout: true, + maxRetries: 2, + signal: abortSignal, + } + ); + }; + public async reinstallTransform() { const esClient = this.options.esClient; const namespace = this.options.namespace; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/utils/create_ingest_pipeline.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/utils/create_ingest_pipeline.ts new file mode 100644 index 0000000000000..183243e98be95 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/utils/create_ingest_pipeline.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 type { ElasticsearchClient } from '@kbn/core/server'; + +export const getIngestPipelineName = (namespace: string): string => { + return `entity_analytics_create_eventIngest_from_timestamp-pipeline-${namespace}`; +}; + +export const createEventIngestedFromTimestamp = async ( + esClient: ElasticsearchClient, + namespace: string +) => { + const ingestTimestampPipeline = getIngestPipelineName(namespace); + + try { + const pipeline = { + id: ingestTimestampPipeline, + body: { + _meta: { + managed_by: 'entity_analytics', + managed: true, + }, + description: 'Pipeline for adding timestamp value to event.ingested', + processors: [ + { + set: { + field: 'event.ingested', + value: '{{_ingest.timestamp}}', + }, + }, + ], + }, + }; + + await esClient.ingest.putPipeline(pipeline); + } catch (e) { + throw new Error(`Error creating ingest pipeline: ${e}`); + } +}; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/mocks.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/mocks.ts index 29df069020561..3b385c70e0b5f 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/mocks.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/mocks.ts @@ -21,6 +21,11 @@ jest.mock('@kbn/security-solution-features/product_features', () => ({ baseKibanaSubFeatureIds: [], subFeaturesMap: new Map(), })), + getSecurityV2Feature: jest.fn(() => ({ + baseKibanaFeature: {}, + baseKibanaSubFeatureIds: [], + subFeaturesMap: new Map(), + })), getCasesFeature: jest.fn(() => ({ baseKibanaFeature: {}, baseKibanaSubFeatureIds: [], @@ -41,6 +46,16 @@ jest.mock('@kbn/security-solution-features/product_features', () => ({ baseKibanaSubFeatureIds: [], subFeaturesMap: new Map(), })), + getTimelineFeature: jest.fn(() => ({ + baseKibanaFeature: {}, + baseKibanaSubFeatureIds: [], + subFeaturesMap: new Map(), + })), + getNotesFeature: jest.fn(() => ({ + baseKibanaFeature: {}, + baseKibanaSubFeatureIds: [], + subFeaturesMap: new Map(), + })), })); export const createProductFeaturesServiceMock = ( @@ -132,6 +147,40 @@ export const createProductFeaturesServiceMock = ( ]) ) ), + timeline: jest.fn().mockReturnValue( + new Map( + enabledFeatureKeys.map((key) => [ + key, + { + privileges: { + all: { + ui: ['entity-analytics'], + }, + read: { + ui: ['entity-analytics'], + }, + }, + }, + ]) + ) + ), + notes: jest.fn().mockReturnValue( + new Map( + enabledFeatureKeys.map((key) => [ + key, + { + privileges: { + all: { + ui: ['entity-analytics'], + }, + read: { + ui: ['entity-analytics'], + }, + }, + }, + ]) + ) + ), }); } diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/product_features_service.test.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/product_features_service.test.ts index 768228f319b24..b0c6254a139a6 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/product_features_service.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/product_features_service.test.ts @@ -46,6 +46,9 @@ jest.mock('@kbn/security-solution-features/product_features', () => ({ getCasesFeature: () => mockGetFeature(), getCasesV2Feature: () => mockGetFeature(), getSecurityFeature: () => mockGetFeature(), + getSecurityV2Feature: () => mockGetFeature(), + getTimelineFeature: () => mockGetFeature(), + getNotesFeature: () => mockGetFeature(), })); describe('ProductFeaturesService', () => { @@ -57,8 +60,8 @@ describe('ProductFeaturesService', () => { const experimentalFeatures = {} as ExperimentalFeatures; new ProductFeaturesService(loggerMock.create(), experimentalFeatures); - expect(mockGetFeature).toHaveBeenCalledTimes(5); - expect(MockedProductFeatures).toHaveBeenCalledTimes(5); + expect(mockGetFeature).toHaveBeenCalledTimes(8); + expect(MockedProductFeatures).toHaveBeenCalledTimes(8); }); it('should init all ProductFeatures when initialized', () => { @@ -90,12 +93,16 @@ describe('ProductFeaturesService', () => { const mockCasesConfig = new Map() as ProductFeaturesConfig; const mockAssistantConfig = new Map() as ProductFeaturesConfig; const mockAttackDiscoveryConfig = new Map() as ProductFeaturesConfig; + const mockTimelineConfig = new Map() as ProductFeaturesConfig; + const mockNotesConfig = new Map() as ProductFeaturesConfig; const configurator: ProductFeaturesConfigurator = { attackDiscovery: jest.fn(() => mockAttackDiscoveryConfig), security: jest.fn(() => mockSecurityConfig), cases: jest.fn(() => mockCasesConfig), securityAssistant: jest.fn(() => mockAssistantConfig), + timeline: jest.fn(() => mockTimelineConfig), + notes: jest.fn(() => mockNotesConfig), }; productFeaturesService.setProductFeaturesConfigurator(configurator); @@ -139,12 +146,16 @@ describe('ProductFeaturesService', () => { const mockAttackDiscoveryConfig = new Map([ [ProductFeatureKey.attackDiscovery, {}], ]) as ProductFeaturesConfig; + const mockTimelineConfig = new Map([[ProductFeatureKey.timeline, {}]]) as ProductFeaturesConfig; + const mockNotesConfig = new Map([[ProductFeatureKey.notes, {}]]) as ProductFeaturesConfig; const configurator: ProductFeaturesConfigurator = { attackDiscovery: jest.fn(() => mockAttackDiscoveryConfig), security: jest.fn(() => mockSecurityConfig), cases: jest.fn(() => mockCasesConfig), securityAssistant: jest.fn(() => mockAssistantConfig), + timeline: jest.fn(() => mockTimelineConfig), + notes: jest.fn(() => mockNotesConfig), }; productFeaturesService.setProductFeaturesConfigurator(configurator); diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/product_features_service.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/product_features_service.ts index 2901734527a93..edcf0faa19659 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/product_features_service.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/product_features_service.ts @@ -21,13 +21,21 @@ import { getCasesFeature, getSecurityFeature, getCasesV2Feature, + getSecurityV2Feature, + getTimelineFeature, + getNotesFeature, } from '@kbn/security-solution-features/product_features'; import type { RecursiveReadonly } from '@kbn/utility-types'; import type { ExperimentalFeatures } from '../../../common'; import { APP_ID } from '../../../common'; import { ProductFeatures } from './product_features'; import type { ProductFeaturesConfigurator } from './types'; -import { securityDefaultSavedObjects } from './security_saved_objects'; +import { + securityDefaultSavedObjects, + securityNotesSavedObjects, + securityTimelineSavedObjects, + securityV1SavedObjects, +} from './security_saved_objects'; import { casesApiTags, casesUiCapabilities } from './cases_privileges'; // The prefix ("securitySolution-") used by all the Security Solution API action privileges. @@ -35,10 +43,13 @@ export const API_ACTION_PREFIX = `${APP_ID}-`; export class ProductFeaturesService { private securityProductFeatures: ProductFeatures; + private securityV2ProductFeatures: ProductFeatures; private casesProductFeatures: ProductFeatures; private casesProductV2Features: ProductFeatures; private securityAssistantProductFeatures: ProductFeatures; private attackDiscoveryProductFeatures: ProductFeatures; + private timelineProductFeatures: ProductFeatures; + private notesProductFeatures: ProductFeatures; private productFeatures?: Set; constructor( @@ -46,7 +57,7 @@ export class ProductFeaturesService { private readonly experimentalFeatures: ExperimentalFeatures ) { const securityFeature = getSecurityFeature({ - savedObjects: securityDefaultSavedObjects, + savedObjects: securityV1SavedObjects, experimentalFeatures: this.experimentalFeatures, }); this.securityProductFeatures = new ProductFeatures( @@ -55,6 +66,16 @@ export class ProductFeaturesService { securityFeature.baseKibanaFeature, securityFeature.baseKibanaSubFeatureIds ); + const securityV2Feature = getSecurityV2Feature({ + savedObjects: securityDefaultSavedObjects, + experimentalFeatures: this.experimentalFeatures, + }); + this.securityV2ProductFeatures = new ProductFeatures( + this.logger, + securityV2Feature.subFeaturesMap, + securityV2Feature.baseKibanaFeature, + securityV2Feature.baseKibanaSubFeatureIds + ); const casesFeature = getCasesFeature({ uiCapabilities: casesUiCapabilities, @@ -91,25 +112,52 @@ export class ProductFeaturesService { ); const attackDiscoveryFeature = getAttackDiscoveryFeature(); + this.attackDiscoveryProductFeatures = new ProductFeatures( this.logger, attackDiscoveryFeature.subFeaturesMap, attackDiscoveryFeature.baseKibanaFeature, attackDiscoveryFeature.baseKibanaSubFeatureIds ); + + const timelineFeature = getTimelineFeature({ + savedObjects: securityTimelineSavedObjects, + experimentalFeatures: {}, + }); + this.timelineProductFeatures = new ProductFeatures( + this.logger, + timelineFeature.subFeaturesMap, + timelineFeature.baseKibanaFeature, + timelineFeature.baseKibanaSubFeatureIds + ); + + const notesFeature = getNotesFeature({ + savedObjects: securityNotesSavedObjects, + experimentalFeatures: {}, + }); + this.notesProductFeatures = new ProductFeatures( + this.logger, + notesFeature.subFeaturesMap, + notesFeature.baseKibanaFeature, + notesFeature.baseKibanaSubFeatureIds + ); } public init(featuresSetup: FeaturesPluginSetup) { this.securityProductFeatures.init(featuresSetup); + this.securityV2ProductFeatures.init(featuresSetup); this.casesProductFeatures.init(featuresSetup); this.casesProductV2Features.init(featuresSetup); this.securityAssistantProductFeatures.init(featuresSetup); this.attackDiscoveryProductFeatures.init(featuresSetup); + this.timelineProductFeatures.init(featuresSetup); + this.notesProductFeatures.init(featuresSetup); } public setProductFeaturesConfigurator(configurator: ProductFeaturesConfigurator) { const securityProductFeaturesConfig = configurator.security(); this.securityProductFeatures.setConfig(securityProductFeaturesConfig); + this.securityV2ProductFeatures.setConfig(securityProductFeaturesConfig); const casesProductFeaturesConfig = configurator.cases(); this.casesProductFeatures.setConfig(casesProductFeaturesConfig); @@ -121,12 +169,20 @@ export class ProductFeaturesService { const attackDiscoveryProductFeaturesConfig = configurator.attackDiscovery(); this.attackDiscoveryProductFeatures.setConfig(attackDiscoveryProductFeaturesConfig); + const timelineProductFeaturesConfig = configurator.timeline(); + this.timelineProductFeatures.setConfig(timelineProductFeaturesConfig); + + const notesProductFeaturesConfig = configurator.notes(); + this.notesProductFeatures.setConfig(notesProductFeaturesConfig); + this.productFeatures = new Set( Object.freeze([ ...securityProductFeaturesConfig.keys(), ...casesProductFeaturesConfig.keys(), ...securityAssistantProductFeaturesConfig.keys(), ...attackDiscoveryProductFeaturesConfig.keys(), + ...timelineProductFeaturesConfig.keys(), + ...notesProductFeaturesConfig.keys(), ]) as readonly ProductFeatureKeyType[] ); } @@ -141,10 +197,13 @@ export class ProductFeaturesService { public isActionRegistered(action: string) { return ( this.securityProductFeatures.isActionRegistered(action) || + this.securityV2ProductFeatures.isActionRegistered(action) || this.casesProductFeatures.isActionRegistered(action) || this.casesProductV2Features.isActionRegistered(action) || this.securityAssistantProductFeatures.isActionRegistered(action) || - this.attackDiscoveryProductFeatures.isActionRegistered(action) + this.attackDiscoveryProductFeatures.isActionRegistered(action) || + this.timelineProductFeatures.isActionRegistered(action) || + this.notesProductFeatures.isActionRegistered(action) ); } diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/security_saved_objects.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/security_saved_objects.ts index b739d44db3e4f..369f1a55e9a5f 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/security_saved_objects.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/security_saved_objects.ts @@ -7,7 +7,12 @@ import { DATA_VIEW_SAVED_OBJECT_TYPE } from '@kbn/data-views-plugin/common'; import { EXCEPTION_LIST_NAMESPACE_AGNOSTIC } from '@kbn/securitysolution-list-constants'; -import { savedObjectTypes } from '../../saved_objects'; +import { + savedObjectTypesWithoutTimelineAndWithoutNotes, + timelineSavedObjectTypes, + notesSavedObjectTypes, + savedObjectTypes, +} from '../../saved_objects'; // Same as the saved-object type for rules defined by Cloud Security Posture const CLOUD_POSTURE_SAVED_OBJECT_RULE_TYPE = 'csp_rule'; @@ -19,8 +24,14 @@ export const securityDefaultSavedObjects = [ 'exception-list', EXCEPTION_LIST_NAMESPACE_AGNOSTIC, DATA_VIEW_SAVED_OBJECT_TYPE, - ...savedObjectTypes, + ...savedObjectTypesWithoutTimelineAndWithoutNotes, CLOUD_POSTURE_SAVED_OBJECT_RULE_TYPE, CLOUD_SECURITY_POSTURE_SETTINGS, CLOUD_SECURITY_POSTURE_BENCHMARK_RULE_TEMPLATE, ]; + +export const securityV1SavedObjects = [...securityDefaultSavedObjects, ...savedObjectTypes]; + +export const securityTimelineSavedObjects = timelineSavedObjectTypes; + +export const securityNotesSavedObjects = notesSavedObjectTypes; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/types.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/types.ts index 9c7b20cfba960..4bc7956c7861f 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/types.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/product_features_service/types.ts @@ -17,4 +17,6 @@ export interface ProductFeaturesConfigurator { security: () => ProductFeaturesConfig; cases: () => ProductFeaturesConfig; securityAssistant: () => ProductFeaturesConfig; + timeline: () => ProductFeaturesConfig; + notes: () => ProductFeaturesConfig; } diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/index.ts index 24d33ea27f23c..5f2049fd8fe12 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/index.ts @@ -18,7 +18,6 @@ import { registerSiemRuleMigrationsStatsAllRoute } from './stats_all'; import { registerSiemRuleMigrationsResourceUpsertRoute } from './resources/upsert'; import { registerSiemRuleMigrationsResourceGetRoute } from './resources/get'; import { registerSiemRuleMigrationsInstallRoute } from './install'; -import { registerSiemRuleMigrationsInstallTranslatedRoute } from './install_translated'; import { registerSiemRuleMigrationsResourceGetMissingRoute } from './resources/missing'; import { registerSiemRuleMigrationsPrebuiltRulesRoute } from './get_prebuilt_rules'; import { registerSiemRuleMigrationsIntegrationsRoute } from './get_integrations'; @@ -37,7 +36,6 @@ export const registerSiemRuleMigrationsRoutes = ( registerSiemRuleMigrationsTranslationStatsRoute(router, logger); registerSiemRuleMigrationsStopRoute(router, logger); registerSiemRuleMigrationsInstallRoute(router, logger); - registerSiemRuleMigrationsInstallTranslatedRoute(router, logger); registerSiemRuleMigrationsIntegrationsRoute(router, logger); registerSiemRuleMigrationsResourceUpsertRoute(router, logger); diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/install.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/install.ts index 9fae2922b486f..386860b307755 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/install.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/install.ts @@ -49,17 +49,16 @@ export const registerSiemRuleMigrationsInstallRoute = ( const savedObjectsClient = ctx.core.savedObjects.client; const rulesClient = await ctx.alerting.getRulesClient(); - await installTranslated({ + const installed = await installTranslated({ migrationId, ids, enabled, securitySolutionContext, savedObjectsClient, rulesClient, - logger, }); - return res.ok({ body: { installed: true } }); + return res.ok({ body: { installed } }); } catch (err) { logger.error(err); return res.badRequest({ body: err.message }); diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/install_translated.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/install_translated.ts deleted file mode 100644 index 2cf2a2e2c8efd..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/install_translated.ts +++ /dev/null @@ -1,68 +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 { IKibanaResponse, Logger } from '@kbn/core/server'; -import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; -import { SIEM_RULE_MIGRATION_INSTALL_TRANSLATED_PATH } from '../../../../../common/siem_migrations/constants'; -import type { InstallTranslatedMigrationRulesResponse } from '../../../../../common/siem_migrations/model/api/rules/rule_migration.gen'; -import { InstallTranslatedMigrationRulesRequestParams } from '../../../../../common/siem_migrations/model/api/rules/rule_migration.gen'; -import type { SecuritySolutionPluginRouter } from '../../../../types'; -import { withLicense } from './util/with_license'; -import { installTranslated } from './util/installation'; - -export const registerSiemRuleMigrationsInstallTranslatedRoute = ( - router: SecuritySolutionPluginRouter, - logger: Logger -) => { - router.versioned - .post({ - path: SIEM_RULE_MIGRATION_INSTALL_TRANSLATED_PATH, - access: 'internal', - security: { authz: { requiredPrivileges: ['securitySolution'] } }, - }) - .addVersion( - { - version: '1', - validate: { - request: { - params: buildRouteValidationWithZod(InstallTranslatedMigrationRulesRequestParams), - }, - }, - }, - withLicense( - async ( - context, - req, - res - ): Promise> => { - const { migration_id: migrationId } = req.params; - - try { - const ctx = await context.resolve(['core', 'alerting', 'securitySolution']); - - const securitySolutionContext = ctx.securitySolution; - const savedObjectsClient = ctx.core.savedObjects.client; - const rulesClient = await ctx.alerting.getRulesClient(); - - await installTranslated({ - migrationId, - enabled: false, - securitySolutionContext, - savedObjectsClient, - rulesClient, - logger, - }); - - return res.ok({ body: { installed: true } }); - } catch (err) { - logger.error(err); - return res.badRequest({ body: err.message }); - } - } - ) - ); -}; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/start.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/start.ts index 130ffe1d80379..d2edd7e6201e9 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/start.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/start.ts @@ -52,10 +52,6 @@ export const registerSiemRuleMigrationsStartRoute = ( const ctx = await context.resolve(['core', 'actions', 'alerting', 'securitySolution']); const ruleMigrationsClient = ctx.securitySolution.getSiemRuleMigrationsClient(); - const inferenceClient = ctx.securitySolution.getInferenceClient(); - const actionsClient = ctx.actions.getActionsClient(); - const soClient = ctx.core.savedObjects.client; - const rulesClient = await ctx.alerting.getRulesClient(); if (retry) { const { updated } = await ruleMigrationsClient.task.updateToRetry( @@ -78,10 +74,6 @@ export const registerSiemRuleMigrationsStartRoute = ( migrationId, connectorId, invocationConfig, - inferenceClient, - actionsClient, - soClient, - rulesClient, }); if (!exists) { diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/util/installation.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/util/installation.ts index de95d818dd18d..978dcbcdb9c35 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/util/installation.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/util/installation.ts @@ -5,8 +5,9 @@ * 2.0. */ -import type { Logger, SavedObjectsClientContract } from '@kbn/core/server'; +import type { SavedObjectsClientContract } from '@kbn/core/server'; import type { RulesClient } from '@kbn/alerting-plugin/server'; +import { getErrorMessage } from '../../../../../utils/error_helpers'; import type { UpdateRuleMigrationData } from '../../../../../../common/siem_migrations/model/rule_migration.gen'; import { initPromisePool } from '../../../../../utils/promise_pool'; import type { SecuritySolutionApiRequestHandlerContext } from '../../../../..'; @@ -16,15 +17,13 @@ import type { IDetectionRulesClient } from '../../../../detection_engine/rule_ma import type { RuleResponse } from '../../../../../../common/api/detection_engine'; import type { StoredRuleMigration } from '../../types'; import { getPrebuiltRules, getUniquePrebuiltRuleIds } from './prebuilt_rules'; -import { - MAX_CUSTOM_RULES_TO_CREATE_IN_PARALLEL, - MAX_TRANSLATED_RULES_TO_INSTALL, -} from '../constants'; import { convertMigrationCustomRuleToSecurityRulePayload, isMigrationCustomRule, } from '../../../../../../common/siem_migrations/rules/utils'; +const MAX_CUSTOM_RULES_TO_CREATE_IN_PARALLEL = 50; + const installPrebuiltRules = async ( rulesToInstall: StoredRuleMigration[], enabled: boolean, @@ -32,7 +31,7 @@ const installPrebuiltRules = async ( rulesClient: RulesClient, savedObjectsClient: SavedObjectsClientContract, detectionRulesClient: IDetectionRulesClient -): Promise => { +): Promise<{ rulesToUpdate: UpdateRuleMigrationData[]; errors: Error[] }> => { // Get required prebuilt rules const prebuiltRulesIds = getUniquePrebuiltRuleIds(rulesToInstall); const prebuiltRules = await getPrebuiltRules(rulesClient, savedObjectsClient, prebuiltRulesIds); @@ -52,13 +51,16 @@ const installPrebuiltRules = async ( } ); + const errors: Error[] = []; + // Install prebuilt rules - // TODO: we need to do an error handling which can happen during the rule installation - const { results: newlyInstalledRules } = await createPrebuiltRules( - detectionRulesClient, - installable + const { results: newlyInstalledRules, errors: installPrebuiltRulesErrors } = + await createPrebuiltRules(detectionRulesClient, installable); + errors.push( + ...installPrebuiltRulesErrors.map( + (err) => new Error(`Error installing prebuilt rule: ${getErrorMessage(err)}`) + ) ); - await performTimelinesInstallation(securitySolutionContext); const installedRules = [ ...alreadyInstalledRules, @@ -81,15 +83,18 @@ const installPrebuiltRules = async ( ); }); - return rulesToUpdate; + return { rulesToUpdate, errors }; }; export const installCustomRules = async ( rulesToInstall: StoredRuleMigration[], enabled: boolean, - detectionRulesClient: IDetectionRulesClient, - logger: Logger -): Promise => { + detectionRulesClient: IDetectionRulesClient +): Promise<{ + rulesToUpdate: UpdateRuleMigrationData[]; + errors: Error[]; +}> => { + const errors: Error[] = []; const rulesToUpdate: UpdateRuleMigrationData[] = []; const createCustomRulesOutcome = await initPromisePool({ concurrency: MAX_CUSTOM_RULES_TO_CREATE_IN_PARALLEL, @@ -113,15 +118,12 @@ export const installCustomRules = async ( }); }, }); - if (createCustomRulesOutcome.errors) { - // TODO: we need to do an error handling which can happen during the rule creation - logger.debug( - `Failed to create some of the rules because of errors: ${JSON.stringify( - createCustomRulesOutcome.errors - )}` - ); - } - return rulesToUpdate; + errors.push( + ...createCustomRulesOutcome.errors.map( + (err) => new Error(`Error installing custom rule: ${getErrorMessage(err)}`) + ) + ); + return { rulesToUpdate, errors }; }; interface InstallTranslatedProps { @@ -155,11 +157,6 @@ interface InstallTranslatedProps { * The saved objects client */ savedObjectsClient: SavedObjectsClientContract; - - /** - * The logger - */ - logger: Logger; } export const installTranslated = async ({ @@ -169,51 +166,63 @@ export const installTranslated = async ({ securitySolutionContext, rulesClient, savedObjectsClient, - logger, -}: InstallTranslatedProps) => { +}: InstallTranslatedProps): Promise => { const detectionRulesClient = securitySolutionContext.getDetectionRulesClient(); const ruleMigrationsClient = securitySolutionContext.getSiemRuleMigrationsClient(); - const { data: rulesToInstall } = await ruleMigrationsClient.data.rules.get(migrationId, { - filters: { ids, installable: true }, - from: 0, - size: MAX_TRANSLATED_RULES_TO_INSTALL, - }); + let installedCount = 0; + const installationErrors: Error[] = []; - const { customRulesToInstall, prebuiltRulesToInstall } = rulesToInstall.reduce( - (acc, item) => { - if (item.elastic_rule?.prebuilt_rule_id) { - acc.prebuiltRulesToInstall.push(item); - } else { - acc.customRulesToInstall.push(item); - } - return acc; - }, - { customRulesToInstall: [], prebuiltRulesToInstall: [] } as { - customRulesToInstall: StoredRuleMigration[]; - prebuiltRulesToInstall: StoredRuleMigration[]; - } - ); - - const updatedPrebuiltRules = await installPrebuiltRules( - prebuiltRulesToInstall, - enabled, - securitySolutionContext, - rulesClient, - savedObjectsClient, - detectionRulesClient - ); - - const updatedCustomRules = await installCustomRules( - customRulesToInstall, - enabled, - detectionRulesClient, - logger - ); + // Install rules that matched Elastic prebuilt rules + const prebuiltRuleBatches = ruleMigrationsClient.data.rules.searchBatches(migrationId, { + filters: { ids, installable: true, prebuilt: true }, + }); + let prebuiltRulesToInstall = await prebuiltRuleBatches.next(); + while (prebuiltRulesToInstall.length) { + const { rulesToUpdate, errors } = await installPrebuiltRules( + prebuiltRulesToInstall, + enabled, + securitySolutionContext, + rulesClient, + savedObjectsClient, + detectionRulesClient + ); + installedCount += rulesToUpdate.length; + installationErrors.push(...errors); + await ruleMigrationsClient.data.rules.update(rulesToUpdate); + prebuiltRulesToInstall = await prebuiltRuleBatches.next(); + } - const rulesToUpdate: UpdateRuleMigrationData[] = [...updatedPrebuiltRules, ...updatedCustomRules]; + let installTimelinesError: string | undefined; + if (installedCount > 0) { + const { error } = await performTimelinesInstallation(securitySolutionContext); + installTimelinesError = error; + } - if (rulesToUpdate.length) { + // Install rules with custom translation + const customRuleBatches = ruleMigrationsClient.data.rules.searchBatches(migrationId, { + filters: { ids, installable: true, prebuilt: false }, + }); + let customRulesToInstall = await customRuleBatches.next(); + while (customRulesToInstall.length) { + const { rulesToUpdate, errors } = await installCustomRules( + customRulesToInstall, + enabled, + detectionRulesClient + ); + installedCount += rulesToUpdate.length; + installationErrors.push(...errors); await ruleMigrationsClient.data.rules.update(rulesToUpdate); + customRulesToInstall = await customRuleBatches.next(); } + + // Throw an error if needed + if (installTimelinesError) { + throw new Error(`Error installing prepackaged timelines: ${installTimelinesError}`); + } + if (installationErrors.length) { + throw new Error(installationErrors.map((err) => err.message).join()); + } + + return installedCount; }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/util/retry.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/util/retry.ts index 700218b4292ee..3f2ce8dafd97e 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/util/retry.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/util/retry.ts @@ -6,7 +6,7 @@ */ import type { RuleMigrationRetryFilter } from '../../../../../../common/siem_migrations/model/rule_migration.gen'; -import type { RuleMigrationFilters } from '../../data/rule_migrations_data_rules_client'; +import type { RuleMigrationFilters } from '../../../../../../common/siem_migrations/types'; const RETRY_FILTERS: Record = { failed: { failed: true }, diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/integrations_temp.json b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/integrations_temp.json deleted file mode 100644 index 9c312bb38e3d6..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/integrations_temp.json +++ /dev/null @@ -1,6881 +0,0 @@ -[ - { - "title": "Containerd", - "id": "containerd", - "description": "Collect metrics from containerd containers.", - "data_streams": [ - { - "dataset": "memory", - "index_pattern": "logs-containerd.memory-*", - "title": "Containerd memory metrics" - }, - { - "dataset": "blkio", - "index_pattern": "logs-containerd.blkio-*", - "title": "Containerd blkio metrics" - }, - { - "dataset": "cpu", - "index_pattern": "logs-containerd.cpu-*", - "title": "Containerd cpu metrics" - } - ], - "elser_embedding": "Containerd - Collect metrics from containerd containers. - Containerd memory metrics Containerd blkio metrics Containerd cpu metrics" - }, - { - "title": "Google Santa", - "id": "santa", - "description": "Collect logs from Google Santa with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-santa.log-*", - "title": "Google Santa log logs" - } - ], - "elser_embedding": "Google Santa - Collect logs from Google Santa with Elastic Agent. - Google Santa log logs" - }, - { - "title": "Keycloak", - "id": "keycloak", - "description": "Collect logs from Keycloak with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-keycloak.log-*", - "title": "Keycloak" - } - ], - "elser_embedding": "Keycloak - Collect logs from Keycloak with Elastic Agent. - Keycloak" - }, - { - "title": "Infoblox NIOS", - "id": "infoblox_nios", - "description": "Collect logs from Infoblox NIOS with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-infoblox_nios.log-*", - "title": "Infoblox NIOS logs" - } - ], - "elser_embedding": "Infoblox NIOS - Collect logs from Infoblox NIOS with Elastic Agent. - Infoblox NIOS logs" - }, - { - "title": "LastPass", - "id": "lastpass", - "description": "Collect logs from LastPass with Elastic Agent.", - "data_streams": [ - { - "dataset": "detailed_shared_folder", - "index_pattern": "logs-lastpass.detailed_shared_folder-*", - "title": "Collect Detailed Shared Folder logs from LastPass" - }, - { - "dataset": "user", - "index_pattern": "logs-lastpass.user-*", - "title": "Collect User logs from LastPass" - }, - { - "dataset": "event_report", - "index_pattern": "logs-lastpass.event_report-*", - "title": "Collect Event Report logs from LastPass" - } - ], - "elser_embedding": "LastPass - Collect logs from LastPass with Elastic Agent. - Collect Detailed Shared Folder logs from LastPass Collect User logs from LastPass Collect Event Report logs from LastPass" - }, - { - "title": "IBM MQ", - "id": "ibmmq", - "description": "Collect logs and metrics from IBM MQ with Elastic Agent.", - "data_streams": [ - { - "dataset": "qmgr", - "index_pattern": "logs-ibmmq.qmgr-*", - "title": "IBM MQ Queue Manager performance metrics" - }, - { - "dataset": "errorlog", - "index_pattern": "logs-ibmmq.errorlog-*", - "title": "IBM MQ Error logs" - } - ], - "elser_embedding": "IBM MQ - Collect logs and metrics from IBM MQ with Elastic Agent. - IBM MQ Queue Manager performance metrics IBM MQ Error logs" - }, - { - "title": "Jamf Protect", - "id": "jamf_protect", - "description": "Receives events from Jamf Protect with Elastic Agent.", - "data_streams": [ - { - "dataset": "web_traffic_events", - "index_pattern": "logs-jamf_protect.web_traffic_events-*", - "title": "Receives Web Traffic Events from Jamf Protect with Elastic Agent." - }, - { - "dataset": "telemetry_legacy", - "index_pattern": "logs-jamf_protect.telemetry_legacy-*", - "title": "Jamf Protect Telemetry (Legacy)." - }, - { - "dataset": "web_threat_events", - "index_pattern": "logs-jamf_protect.web_threat_events-*", - "title": "Receives Web Threat Events from Jamf Protect with Elastic Agent." - }, - { - "dataset": "telemetry", - "index_pattern": "logs-jamf_protect.telemetry-*", - "title": "Receives Telemetry from Jamf Protect with Elastic Agent." - }, - { - "dataset": "alerts", - "index_pattern": "logs-jamf_protect.alerts-*", - "title": "Receives Alerts from Jamf Protect with Elastic Agent." - } - ], - "elser_embedding": "Jamf Protect - Receives events from Jamf Protect with Elastic Agent. - Receives Web Traffic Events from Jamf Protect with Elastic Agent. Jamf Protect Telemetry (Legacy). Receives Web Threat Events from Jamf Protect with Elastic Agent. Receives Telemetry from Jamf Protect with Elastic Agent. Receives Alerts from Jamf Protect with Elastic Agent." - }, - { - "title": "Sysmon for Linux", - "id": "sysmon_linux", - "description": "Collect Sysmon Linux logs with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-sysmon_linux.log-*", - "title": "Sysmon for Linux logs" - } - ], - "elser_embedding": "Sysmon for Linux - Collect Sysmon Linux logs with Elastic Agent. - Sysmon for Linux logs" - }, - { - "title": "Trend Micro Deep Security", - "id": "trendmicro", - "description": "Collect logs from Trend Micro Deep Security with Elastic Agent.", - "data_streams": [ - { - "dataset": "deep_security", - "index_pattern": "logs-trendmicro.deep_security-*", - "title": "Collect logs from Trend Micro Deep Security" - } - ], - "elser_embedding": "Trend Micro Deep Security - Collect logs from Trend Micro Deep Security with Elastic Agent. - Collect logs from Trend Micro Deep Security" - }, - { - "title": "HAProxy", - "id": "haproxy", - "description": "Collect logs and metrics from HAProxy servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "info", - "index_pattern": "logs-haproxy.info-*", - "title": "HAProxy info metrics" - }, - { - "dataset": "stat", - "index_pattern": "logs-haproxy.stat-*", - "title": "HAProxy stat metrics" - }, - { - "dataset": "log", - "index_pattern": "logs-haproxy.log-*", - "title": "HAProxy logs" - } - ], - "elser_embedding": "HAProxy - Collect logs and metrics from HAProxy servers with Elastic Agent. - HAProxy info metrics HAProxy stat metrics HAProxy logs" - }, - { - "title": "ESET Threat Intelligence", - "id": "ti_eset", - "description": "Ingest threat intelligence indicators from ESET Threat Intelligence with Elastic Agent.", - "data_streams": [ - { - "dataset": "cc", - "index_pattern": "logs-ti_eset.cc-*", - "title": "Botnet C&C" - }, - { - "dataset": "url", - "index_pattern": "logs-ti_eset.url-*", - "title": "URL" - }, - { - "dataset": "domains", - "index_pattern": "logs-ti_eset.domains-*", - "title": "Domain" - }, - { - "dataset": "files", - "index_pattern": "logs-ti_eset.files-*", - "title": "Malicious files" - }, - { - "dataset": "apt", - "index_pattern": "logs-ti_eset.apt-*", - "title": "APT" - }, - { - "dataset": "ip", - "index_pattern": "logs-ti_eset.ip-*", - "title": "IP" - }, - { - "dataset": "botnet", - "index_pattern": "logs-ti_eset.botnet-*", - "title": "Botnet" - } - ], - "elser_embedding": "ESET Threat Intelligence - Ingest threat intelligence indicators from ESET Threat Intelligence with Elastic Agent. - Botnet C&C URL Domain Malicious files APT IP Botnet" - }, - { - "title": "Lyve Cloud", - "id": "lyve_cloud", - "description": "Collect S3 API audit log from Lyve Cloud with Elastic Agent.", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-lyve_cloud.audit-*", - "title": "Lyve Cloud logs" - } - ], - "elser_embedding": "Lyve Cloud - Collect S3 API audit log from Lyve Cloud with Elastic Agent. - Lyve Cloud logs" - }, - { - "title": "Tanium", - "id": "tanium", - "description": "This Elastic integration collects logs from Tanium with Elastic Agent.", - "data_streams": [ - { - "dataset": "discover", - "index_pattern": "logs-tanium.discover-*", - "title": "Collect Tanium Discover logs from Tanium" - }, - { - "dataset": "threat_response", - "index_pattern": "logs-tanium.threat_response-*", - "title": "Collect Threat Response logs from Tanium." - }, - { - "dataset": "client_status", - "index_pattern": "logs-tanium.client_status-*", - "title": "Client Status" - }, - { - "dataset": "reporting", - "index_pattern": "logs-tanium.reporting-*", - "title": "Reporting" - }, - { - "dataset": "action_history", - "index_pattern": "logs-tanium.action_history-*", - "title": "Collect Action History logs from Tanium." - }, - { - "dataset": "endpoint_config", - "index_pattern": "logs-tanium.endpoint_config-*", - "title": "Collect Endpoint Config logs from Tanium" - } - ], - "elser_embedding": "Tanium - This Elastic integration collects logs from Tanium with Elastic Agent. - Collect Tanium Discover logs from Tanium Collect Threat Response logs from Tanium. Client Status Reporting Collect Action History logs from Tanium. Collect Endpoint Config logs from Tanium" - }, - { - "title": "SonicWall Firewall", - "id": "sonicwall_firewall", - "description": "Integration for SonicWall firewall logs", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-sonicwall_firewall.log-*", - "title": "SonicWall Firewall logs" - } - ], - "elser_embedding": "SonicWall Firewall - Integration for SonicWall firewall logs - SonicWall Firewall logs" - }, - { - "title": "STAN", - "id": "stan", - "description": "Collect logs and metrics from STAN servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "stats", - "index_pattern": "logs-stan.stats-*", - "title": "Stan stats metrics" - }, - { - "dataset": "subscriptions", - "index_pattern": "logs-stan.subscriptions-*", - "title": "Stan subscriptions metrics" - }, - { - "dataset": "channels", - "index_pattern": "logs-stan.channels-*", - "title": "Stan channels metrics" - }, - { - "dataset": "log", - "index_pattern": "logs-stan.log-*", - "title": "STAN logs" - } - ], - "elser_embedding": "STAN - Collect logs and metrics from STAN servers with Elastic Agent. - Stan stats metrics Stan subscriptions metrics Stan channels metrics STAN logs" - }, - { - "title": "Amazon Bedrock", - "id": "aws_bedrock", - "description": "Collect Amazon Bedrock model invocation logs and runtime metrics with Elastic Agent.", - "data_streams": [ - { - "dataset": "runtime", - "index_pattern": "logs-aws_bedrock.runtime-*", - "title": "Amazon Bedrock Runtime Metrics" - }, - { - "dataset": "invocation", - "index_pattern": "logs-aws_bedrock.invocation-*", - "title": "Amazon Bedrock model invocation logs" - } - ], - "elser_embedding": "Amazon Bedrock - Collect Amazon Bedrock model invocation logs and runtime metrics with Elastic Agent. - Amazon Bedrock Runtime Metrics Amazon Bedrock model invocation logs" - }, - { - "title": "Microsoft M365 Defender", - "id": "m365_defender", - "description": "Collect logs from Microsoft M365 Defender with Elastic Agent.", - "data_streams": [ - { - "dataset": "alert", - "index_pattern": "logs-m365_defender.alert-*", - "title": "Collect Alert logs from Microsoft 365 Defender" - }, - { - "dataset": "log", - "index_pattern": "logs-m365_defender.log-*", - "title": "M365 Defender Logs" - }, - { - "dataset": "incident", - "index_pattern": "logs-m365_defender.incident-*", - "title": "Collect Incident logs from Microsoft 365 Defender" - }, - { - "dataset": "event", - "index_pattern": "logs-m365_defender.event-*", - "title": "Collect Event logs from Microsoft 365 Defender." - } - ], - "elser_embedding": "Microsoft M365 Defender - Collect logs from Microsoft M365 Defender with Elastic Agent. - Collect Alert logs from Microsoft 365 Defender M365 Defender Logs Collect Incident logs from Microsoft 365 Defender Collect Event logs from Microsoft 365 Defender." - }, - { - "title": "NATS", - "id": "nats", - "description": "Collect logs and metrics from NATS servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "stats", - "index_pattern": "logs-nats.stats-*", - "title": "NATS stats metrics" - }, - { - "dataset": "route", - "index_pattern": "logs-nats.route-*", - "title": "NATS route metrics" - }, - { - "dataset": "connection", - "index_pattern": "logs-nats.connection-*", - "title": "NATS connection metrics" - }, - { - "dataset": "subscriptions", - "index_pattern": "logs-nats.subscriptions-*", - "title": "NATS subscriptions metrics" - }, - { - "dataset": "log", - "index_pattern": "logs-nats.log-*", - "title": "NATS logs" - }, - { - "dataset": "routes", - "index_pattern": "logs-nats.routes-*", - "title": "NATS routes metrics" - }, - { - "dataset": "connections", - "index_pattern": "logs-nats.connections-*", - "title": "NATS connections metrics" - } - ], - "elser_embedding": "NATS - Collect logs and metrics from NATS servers with Elastic Agent. - NATS stats metrics NATS route metrics NATS connection metrics NATS subscriptions metrics NATS logs NATS routes metrics NATS connections metrics" - }, - { - "title": "GoFlow2 logs", - "id": "goflow2", - "description": "Collect logs from goflow2 with Elastic Agent.", - "data_streams": [ - { - "dataset": "sflow", - "index_pattern": "logs-goflow2.sflow-*", - "title": "Goflow2 sFlow" - } - ], - "elser_embedding": "GoFlow2 logs - Collect logs from goflow2 with Elastic Agent. - Goflow2 sFlow" - }, - { - "title": "Microsoft Defender for Cloud", - "id": "microsoft_defender_cloud", - "description": "Collect logs from Microsoft Defender for Cloud with Elastic Agent.", - "data_streams": [ - { - "dataset": "event", - "index_pattern": "logs-microsoft_defender_cloud.event-*", - "title": "Collect Event(Alert and Recommendation) logs from Microsoft Defender for Cloud." - } - ], - "elser_embedding": "Microsoft Defender for Cloud - Collect logs from Microsoft Defender for Cloud with Elastic Agent. - Collect Event(Alert and Recommendation) logs from Microsoft Defender for Cloud." - }, - { - "title": "RabbitMQ Logs and Metrics", - "id": "rabbitmq", - "description": "Collect and parse logs from RabbitMQ servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "queue", - "index_pattern": "logs-rabbitmq.queue-*", - "title": "RabbitMQ queue metrics" - }, - { - "dataset": "exchange", - "index_pattern": "logs-rabbitmq.exchange-*", - "title": "RabbitMQ exchange metrics" - }, - { - "dataset": "connection", - "index_pattern": "logs-rabbitmq.connection-*", - "title": "RabbitMQ connection metrics" - }, - { - "dataset": "log", - "index_pattern": "logs-rabbitmq.log-*", - "title": "RabbitMQ application logs" - }, - { - "dataset": "node", - "index_pattern": "logs-rabbitmq.node-*", - "title": "RabbitMQ node metrics" - } - ], - "elser_embedding": "RabbitMQ Logs and Metrics - Collect and parse logs from RabbitMQ servers with Elastic Agent. - RabbitMQ queue metrics RabbitMQ exchange metrics RabbitMQ connection metrics RabbitMQ application logs RabbitMQ node metrics" - }, - { - "title": "Apache Tomcat", - "id": "apache_tomcat", - "description": "Collect and parse logs and metrics from Apache Tomcat servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "catalina", - "index_pattern": "logs-apache_tomcat.catalina-*", - "title": "Apache Tomcat Catalina logs" - }, - { - "dataset": "memory", - "index_pattern": "logs-apache_tomcat.memory-*", - "title": "Apache Tomcat Memory metrics" - }, - { - "dataset": "access", - "index_pattern": "logs-apache_tomcat.access-*", - "title": "Apache Tomcat Access logs" - }, - { - "dataset": "cache", - "index_pattern": "logs-apache_tomcat.cache-*", - "title": "Apache Tomcat Cache metrics" - }, - { - "dataset": "request", - "index_pattern": "logs-apache_tomcat.request-*", - "title": "Apache Tomcat Request metrics" - }, - { - "dataset": "session", - "index_pattern": "logs-apache_tomcat.session-*", - "title": "Apache Tomcat Session metrics" - }, - { - "dataset": "localhost", - "index_pattern": "logs-apache_tomcat.localhost-*", - "title": "Apache Tomcat Localhost logs" - }, - { - "dataset": "connection_pool", - "index_pattern": "logs-apache_tomcat.connection_pool-*", - "title": "Apache Tomcat Connection Pool metrics" - }, - { - "dataset": "thread_pool", - "index_pattern": "logs-apache_tomcat.thread_pool-*", - "title": "Apache Tomcat Thread Pool metrics" - } - ], - "elser_embedding": "Apache Tomcat - Collect and parse logs and metrics from Apache Tomcat servers with Elastic Agent. - Apache Tomcat Catalina logs Apache Tomcat Memory metrics Apache Tomcat Access logs Apache Tomcat Cache metrics Apache Tomcat Request metrics Apache Tomcat Session metrics Apache Tomcat Localhost logs Apache Tomcat Connection Pool metrics Apache Tomcat Thread Pool metrics" - }, - { - "title": "CylanceProtect Logs", - "id": "cylance", - "description": "Collect logs from CylanceProtect devices with Elastic Agent.", - "data_streams": [ - { - "dataset": "protect", - "index_pattern": "logs-cylance.protect-*", - "title": "CylanceProtect logs" - } - ], - "elser_embedding": "CylanceProtect Logs - Collect logs from CylanceProtect devices with Elastic Agent. - CylanceProtect logs" - }, - { - "title": "Rapid7 InsightVM", - "id": "rapid7_insightvm", - "description": "Collect logs from Rapid7 InsightVM with Elastic Agent.", - "data_streams": [ - { - "dataset": "vulnerability", - "index_pattern": "logs-rapid7_insightvm.vulnerability-*", - "title": "Collect Vulnerability logs from Rapid7 InsightVM" - }, - { - "dataset": "asset", - "index_pattern": "logs-rapid7_insightvm.asset-*", - "title": "Collect Asset logs from Rapid7 InsightVM" - } - ], - "elser_embedding": "Rapid7 InsightVM - Collect logs from Rapid7 InsightVM with Elastic Agent. - Collect Vulnerability logs from Rapid7 InsightVM Collect Asset logs from Rapid7 InsightVM" - }, - { - "title": "Symantec EDR Cloud", - "id": "symantec_edr_cloud", - "description": "Collect logs from Symantec EDR Cloud with Elastic Agent.", - "data_streams": [ - { - "dataset": "incident", - "index_pattern": "logs-symantec_edr_cloud.incident-*", - "title": "Collect Incident logs from Symantec EDR Cloud" - } - ], - "elser_embedding": "Symantec EDR Cloud - Collect logs from Symantec EDR Cloud with Elastic Agent. - Collect Incident logs from Symantec EDR Cloud" - }, - { - "title": "Nginx Ingress Controller OpenTelemetry Logs", - "id": "nginx_ingress_controller_otel", - "description": "Collect Nginx Ingress Controller logs using the OpenTelemetry collector.", - "data_streams": [], - "elser_embedding": "Nginx Ingress Controller OpenTelemetry Logs - Collect Nginx Ingress Controller logs using the OpenTelemetry collector. - " - }, - { - "title": "OpenCTI", - "id": "ti_opencti", - "description": "Ingest threat intelligence indicators from OpenCTI with Elastic Agent.", - "data_streams": [ - { - "dataset": "indicator", - "index_pattern": "logs-ti_opencti.indicator-*", - "title": "Indicator" - } - ], - "elser_embedding": "OpenCTI - Ingest threat intelligence indicators from OpenCTI with Elastic Agent. - Indicator" - }, - { - "title": "Windows", - "id": "windows", - "description": "Collect logs and metrics from Windows OS and services with Elastic Agent.", - "data_streams": [ - { - "dataset": "applocker_packaged_app_deployment", - "index_pattern": "logs-windows.applocker_packaged_app_deployment-*", - "title": "Windows AppLocker/Packaged app-Deployment logs" - }, - { - "dataset": "applocker_msi_and_script", - "index_pattern": "logs-windows.applocker_msi_and_script-*", - "title": "Windows AppLocker/MSI and Script logs" - }, - { - "dataset": "powershell_operational", - "index_pattern": "logs-windows.powershell_operational-*", - "title": "Windows Powershell/Operational logs" - }, - { - "dataset": "perfmon", - "index_pattern": "logs-windows.perfmon-*", - "title": "Windows perfmon metrics" - }, - { - "dataset": "windows_defender", - "index_pattern": "logs-windows.windows_defender-*", - "title": "Windows Defender logs" - }, - { - "dataset": "sysmon_operational", - "index_pattern": "logs-windows.sysmon_operational-*", - "title": "Windows Sysmon/Operational events" - }, - { - "dataset": "service", - "index_pattern": "logs-windows.service-*", - "title": "Windows service metrics" - }, - { - "dataset": "forwarded", - "index_pattern": "logs-windows.forwarded-*", - "title": "Windows forwarded events" - }, - { - "dataset": "powershell", - "index_pattern": "logs-windows.powershell-*", - "title": "Windows Powershell logs" - }, - { - "dataset": "applocker_exe_and_dll", - "index_pattern": "logs-windows.applocker_exe_and_dll-*", - "title": "Windows AppLocker/EXE and DLL logs" - }, - { - "dataset": "applocker_packaged_app_execution", - "index_pattern": "logs-windows.applocker_packaged_app_execution-*", - "title": "Windows AppLocker/Packaged app-Execution logs" - } - ], - "elser_embedding": "Windows - Collect logs and metrics from Windows OS and services with Elastic Agent. - Windows AppLocker/Packaged app-Deployment logs Windows AppLocker/MSI and Script logs Windows Powershell/Operational logs Windows perfmon metrics Windows Defender logs Windows Sysmon/Operational events Windows service metrics Windows forwarded events Windows Powershell logs Windows AppLocker/EXE and DLL logs Windows AppLocker/Packaged app-Execution logs" - }, - { - "title": "CouchDB", - "id": "couchdb", - "description": "Collect metrics from CouchDB with Elastic Agent.", - "data_streams": [ - { - "dataset": "server", - "index_pattern": "logs-couchdb.server-*", - "title": "Server" - } - ], - "elser_embedding": "CouchDB - Collect metrics from CouchDB with Elastic Agent. - Server" - }, - { - "title": "Custom UDP Logs", - "id": "udp", - "description": "Collect raw UDP data from listening UDP port with Elastic Agent.", - "data_streams": [ - { - "dataset": "generic", - "index_pattern": "logs-udp.generic-*", - "title": "Custom UDP Logs" - } - ], - "elser_embedding": "Custom UDP Logs - Collect raw UDP data from listening UDP port with Elastic Agent. - Custom UDP Logs" - }, - { - "title": "Cassandra", - "id": "cassandra", - "description": "This Elastic integration collects logs and metrics from cassandra.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-cassandra.log-*", - "title": "Cassandra System Logs" - }, - { - "dataset": "metrics", - "index_pattern": "logs-cassandra.metrics-*", - "title": "Metrics" - } - ], - "elser_embedding": "Cassandra - This Elastic integration collects logs and metrics from cassandra. - Cassandra System Logs Metrics" - }, - { - "title": "Gigamon", - "id": "gigamon", - "description": "Collect logs from Gigamon with Elastic Agent.", - "data_streams": [ - { - "dataset": "ami", - "index_pattern": "logs-gigamon.ami-*", - "title": "Gigamon Application Metadata Intelligence (AMI) Logs" - } - ], - "elser_embedding": "Gigamon - Collect logs from Gigamon with Elastic Agent. - Gigamon Application Metadata Intelligence (AMI) Logs" - }, - { - "title": "Hashicorp Vault", - "id": "hashicorp_vault", - "description": "Collect logs and metrics from Hashicorp Vault with Elastic Agent.", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-hashicorp_vault.audit-*", - "title": "Hashicorp Vault Audit Logs" - }, - { - "dataset": "log", - "index_pattern": "logs-hashicorp_vault.log-*", - "title": "Hashicorp Vault Operational Logs" - }, - { - "dataset": "metrics", - "index_pattern": "logs-hashicorp_vault.metrics-*", - "title": "Hashicorp Vault Metrics" - } - ], - "elser_embedding": "Hashicorp Vault - Collect logs and metrics from Hashicorp Vault with Elastic Agent. - Hashicorp Vault Audit Logs Hashicorp Vault Operational Logs Hashicorp Vault Metrics" - }, - { - "title": "Okta", - "id": "okta", - "description": "Collect and parse event logs from Okta API with Elastic Agent.", - "data_streams": [ - { - "dataset": "system", - "index_pattern": "logs-okta.system-*", - "title": "Okta system logs" - } - ], - "elser_embedding": "Okta - Collect and parse event logs from Okta API with Elastic Agent. - Okta system logs" - }, - { - "title": "Recorded Future", - "id": "ti_recordedfuture", - "description": "Ingest threat intelligence indicators from Recorded Future risk lists with Elastic Agent.", - "data_streams": [ - { - "dataset": "threat", - "index_pattern": "logs-ti_recordedfuture.threat-*", - "title": "Recorded Future" - } - ], - "elser_embedding": "Recorded Future - Ingest threat intelligence indicators from Recorded Future risk lists with Elastic Agent. - Recorded Future" - }, - { - "title": "IIS", - "id": "iis", - "description": "Collect logs and metrics from Internet Information Services (IIS) servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "access", - "index_pattern": "logs-iis.access-*", - "title": "IIS access logs" - }, - { - "dataset": "webserver", - "index_pattern": "logs-iis.webserver-*", - "title": "IIS web server metrics" - }, - { - "dataset": "error", - "index_pattern": "logs-iis.error-*", - "title": "IIS error logs" - }, - { - "dataset": "website", - "index_pattern": "logs-iis.website-*", - "title": "IIS website metrics" - }, - { - "dataset": "application_pool", - "index_pattern": "logs-iis.application_pool-*", - "title": "IIS application_pool metrics" - } - ], - "elser_embedding": "IIS - Collect logs and metrics from Internet Information Services (IIS) servers with Elastic Agent. - IIS access logs IIS web server metrics IIS error logs IIS website metrics IIS application_pool metrics" - }, - { - "title": "Golang", - "id": "golang", - "description": "This Elastic integration collects metrics from Golang applications.", - "data_streams": [ - { - "dataset": "heap", - "index_pattern": "logs-golang.heap-*", - "title": "Golang Heap metrics" - }, - { - "dataset": "expvar", - "index_pattern": "logs-golang.expvar-*", - "title": "Golang expvar metrics" - } - ], - "elser_embedding": "Golang - This Elastic integration collects metrics from Golang applications. - Golang Heap metrics Golang expvar metrics" - }, - { - "title": "MongoDB", - "id": "mongodb", - "description": "Collect logs and metrics from MongoDB instances with Elastic Agent.", - "data_streams": [ - { - "dataset": "replstatus", - "index_pattern": "logs-mongodb.replstatus-*", - "title": "MongoDB replstatus metrics" - }, - { - "dataset": "log", - "index_pattern": "logs-mongodb.log-*", - "title": "mongodb log logs" - }, - { - "dataset": "metrics", - "index_pattern": "logs-mongodb.metrics-*", - "title": "MongoDB metrics" - }, - { - "dataset": "status", - "index_pattern": "logs-mongodb.status-*", - "title": "MongoDB status metrics" - }, - { - "dataset": "dbstats", - "index_pattern": "logs-mongodb.dbstats-*", - "title": "MongoDB dbstats metrics" - }, - { - "dataset": "collstats", - "index_pattern": "logs-mongodb.collstats-*", - "title": "MongoDB collstats metrics" - } - ], - "elser_embedding": "MongoDB - Collect logs and metrics from MongoDB instances with Elastic Agent. - MongoDB replstatus metrics mongodb log logs MongoDB metrics MongoDB status metrics MongoDB dbstats metrics MongoDB collstats metrics" - }, - { - "title": "Sublime Security", - "id": "sublime_security", - "description": "Collect logs from Sublime Security with Elastic Agent.", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-sublime_security.audit-*", - "title": "Sublime Security Audit logs" - }, - { - "dataset": "email_message", - "index_pattern": "logs-sublime_security.email_message-*", - "title": "Sublime Security Email Message logs" - }, - { - "dataset": "message_event", - "index_pattern": "logs-sublime_security.message_event-*", - "title": "Sublime Security Message Event logs" - } - ], - "elser_embedding": "Sublime Security - Collect logs from Sublime Security with Elastic Agent. - Sublime Security Audit logs Sublime Security Email Message logs Sublime Security Message Event logs" - }, - { - "title": "Nginx", - "id": "nginx", - "description": "Collect logs and metrics from Nginx HTTP servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "access", - "index_pattern": "logs-nginx.access-*", - "title": "Nginx access logs" - }, - { - "dataset": "error", - "index_pattern": "logs-nginx.error-*", - "title": "Nginx error logs" - }, - { - "dataset": "stubstatus", - "index_pattern": "logs-nginx.stubstatus-*", - "title": "Nginx stubstatus metrics" - } - ], - "elser_embedding": "Nginx - Collect logs and metrics from Nginx HTTP servers with Elastic Agent. - Nginx access logs Nginx error logs Nginx stubstatus metrics" - }, - { - "title": "Apache Spark", - "id": "apache_spark", - "description": "Collect metrics from Apache Spark with Elastic Agent.", - "data_streams": [ - { - "dataset": "driver", - "index_pattern": "logs-apache_spark.driver-*", - "title": "Apache Spark driver metrics" - }, - { - "dataset": "application", - "index_pattern": "logs-apache_spark.application-*", - "title": "Apache Spark application metrics" - }, - { - "dataset": "node", - "index_pattern": "logs-apache_spark.node-*", - "title": "Apache Spark node metrics" - }, - { - "dataset": "executor", - "index_pattern": "logs-apache_spark.executor-*", - "title": "Apache Spark executor metrics" - } - ], - "elser_embedding": "Apache Spark - Collect metrics from Apache Spark with Elastic Agent. - Apache Spark driver metrics Apache Spark application metrics Apache Spark node metrics Apache Spark executor metrics" - }, - { - "title": "Rapid7 Threat Command", - "id": "ti_rapid7_threat_command", - "description": "Collect threat intelligence from Threat Command API with Elastic Agent.", - "data_streams": [ - { - "dataset": "ioc", - "index_pattern": "logs-ti_rapid7_threat_command.ioc-*", - "title": "Rapid7 Threat Command IOCs" - }, - { - "dataset": "vulnerability", - "index_pattern": "logs-ti_rapid7_threat_command.vulnerability-*", - "title": "Rapid7 Threat Command Vulnerability" - }, - { - "dataset": "alert", - "index_pattern": "logs-ti_rapid7_threat_command.alert-*", - "title": "Rapid7 Threat Command Alerts" - } - ], - "elser_embedding": "Rapid7 Threat Command - Collect threat intelligence from Threat Command API with Elastic Agent. - Rapid7 Threat Command IOCs Rapid7 Threat Command Vulnerability Rapid7 Threat Command Alerts" - }, - { - "title": "Fortinet FortiEDR Logs", - "id": "fortinet_fortiedr", - "description": "Collect logs from Fortinet FortiEDR instances with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-fortinet_fortiedr.log-*", - "title": "Fortinet FortEDR Endpoint Detection and Response logs" - } - ], - "elser_embedding": "Fortinet FortiEDR Logs - Collect logs from Fortinet FortiEDR instances with Elastic Agent. - Fortinet FortEDR Endpoint Detection and Response logs" - }, - { - "title": "ThreatQuotient", - "id": "ti_threatq", - "description": "Ingest threat intelligence indicators from ThreatQuotient with Elastic Agent.", - "data_streams": [ - { - "dataset": "threat", - "index_pattern": "logs-ti_threatq.threat-*", - "title": "ThreatQ" - } - ], - "elser_embedding": "ThreatQuotient - Ingest threat intelligence indicators from ThreatQuotient with Elastic Agent. - ThreatQ" - }, - { - "title": "BBOT (Bighuge BLS OSINT Tool)", - "id": "bbot", - "description": "BBOT is a recursive internet scanner inspired by Spiderfoot, but designed to be faster, more reliable, and friendlier to pentesters, bug bounty hunters, and developers. ", - "data_streams": [ - { - "dataset": "asm_intel", - "index_pattern": "logs-bbot.asm_intel-*", - "title": "BBOT-Data-Ingest" - } - ], - "elser_embedding": "BBOT (Bighuge BLS OSINT Tool) - BBOT is a recursive internet scanner inspired by Spiderfoot, but designed to be faster, more reliable, and friendlier to pentesters, bug bounty hunters, and developers. - BBOT-Data-Ingest" - }, - { - "title": "Microsoft SQL Server", - "id": "microsoft_sqlserver", - "description": "Collect events from Microsoft SQL Server with Elastic Agent", - "data_streams": [ - { - "dataset": "performance", - "index_pattern": "logs-microsoft_sqlserver.performance-*", - "title": "Microsoft SQL Server performance metrics" - }, - { - "dataset": "audit", - "index_pattern": "logs-microsoft_sqlserver.audit-*", - "title": "SQL Server audit events" - }, - { - "dataset": "log", - "index_pattern": "logs-microsoft_sqlserver.log-*", - "title": "Microsoft SQL Server error logs" - }, - { - "dataset": "transaction_log", - "index_pattern": "logs-microsoft_sqlserver.transaction_log-*", - "title": "Microsoft SQL Server transaction_log metrics" - } - ], - "elser_embedding": "Microsoft SQL Server - Collect events from Microsoft SQL Server with Elastic Agent - Microsoft SQL Server performance metrics SQL Server audit events Microsoft SQL Server error logs Microsoft SQL Server transaction_log metrics" - }, - { - "title": "Claroty CTD", - "id": "claroty_ctd", - "description": "Collect logs from Claroty CTD using Elastic Agent.", - "data_streams": [ - { - "dataset": "baseline", - "index_pattern": "logs-claroty_ctd.baseline-*", - "title": "Baseline logs" - }, - { - "dataset": "event", - "index_pattern": "logs-claroty_ctd.event-*", - "title": "Event logs" - }, - { - "dataset": "asset", - "index_pattern": "logs-claroty_ctd.asset-*", - "title": "Asset logs" - } - ], - "elser_embedding": "Claroty CTD - Collect logs from Claroty CTD using Elastic Agent. - Baseline logs Event logs Asset logs" - }, - { - "title": "ZeroFox", - "id": "zerofox", - "description": "Collect logs from ZeroFox with Elastic Agent.", - "data_streams": [ - { - "dataset": "alerts", - "index_pattern": "logs-zerofox.alerts-*", - "title": "Alerts" - } - ], - "elser_embedding": "ZeroFox - Collect logs from ZeroFox with Elastic Agent. - Alerts" - }, - { - "title": "Darktrace", - "id": "darktrace", - "description": "Collect logs from Darktrace with Elastic Agent.", - "data_streams": [ - { - "dataset": "system_status_alert", - "index_pattern": "logs-darktrace.system_status_alert-*", - "title": "Collect System Status Alert logs from Darktrace" - }, - { - "dataset": "model_breach_alert", - "index_pattern": "logs-darktrace.model_breach_alert-*", - "title": "Collect Model Breach Alert logs from Darktrace" - }, - { - "dataset": "ai_analyst_alert", - "index_pattern": "logs-darktrace.ai_analyst_alert-*", - "title": "Collect AI Analyst Alert logs from Darktrace" - } - ], - "elser_embedding": "Darktrace - Collect logs from Darktrace with Elastic Agent. - Collect System Status Alert logs from Darktrace Collect Model Breach Alert logs from Darktrace Collect AI Analyst Alert logs from Darktrace" - }, - { - "title": "Cybersixgill", - "id": "ti_cybersixgill", - "description": "Ingest threat intelligence indicators from Cybersixgill with Elastic Agent.", - "data_streams": [ - { - "dataset": "threat", - "index_pattern": "logs-ti_cybersixgill.threat-*", - "title": "Cybersixgill Darkfeed Logs" - } - ], - "elser_embedding": "Cybersixgill - Ingest threat intelligence indicators from Cybersixgill with Elastic Agent. - Cybersixgill Darkfeed Logs" - }, - { - "title": "Trend Micro Vision One", - "id": "trend_micro_vision_one", - "description": "Collect logs from Trend Micro Vision One with Elastic Agent.", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-trend_micro_vision_one.audit-*", - "title": "Collect Audit logs from Trend Micro Vision One." - }, - { - "dataset": "alert", - "index_pattern": "logs-trend_micro_vision_one.alert-*", - "title": "Collect Alert logs from Trend Micro Vision One." - }, - { - "dataset": "detection", - "index_pattern": "logs-trend_micro_vision_one.detection-*", - "title": "Collect Detection logs from Trend Micro Vision One." - } - ], - "elser_embedding": "Trend Micro Vision One - Collect logs from Trend Micro Vision One with Elastic Agent. - Collect Audit logs from Trend Micro Vision One. Collect Alert logs from Trend Micro Vision One. Collect Detection logs from Trend Micro Vision One." - }, - { - "title": "Traefik", - "id": "traefik", - "description": "Collect logs from Traefik servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "access", - "index_pattern": "logs-traefik.access-*", - "title": "Traefik access logs" - }, - { - "dataset": "health", - "index_pattern": "logs-traefik.health-*", - "title": "Traefik health metrics" - } - ], - "elser_embedding": "Traefik - Collect logs from Traefik servers with Elastic Agent. - Traefik access logs Traefik health metrics" - }, - { - "title": "F5 BIG-IP", - "id": "f5_bigip", - "description": "Collect logs from F5 BIG-IP with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-f5_bigip.log-*", - "title": "Collect logs from F5 BIG-IP" - } - ], - "elser_embedding": "F5 BIG-IP - Collect logs from F5 BIG-IP with Elastic Agent. - Collect logs from F5 BIG-IP" - }, - { - "title": "Custom Kafka Logs", - "id": "kafka_log", - "description": "Collect data from kafka topic with Elastic Agent.", - "data_streams": [ - { - "dataset": "generic", - "index_pattern": "logs-kafka_log.generic-*", - "title": "Custom Kafka Logs" - } - ], - "elser_embedding": "Custom Kafka Logs - Collect data from kafka topic with Elastic Agent. - Custom Kafka Logs" - }, - { - "title": "CyberArk Privileged Access Security", - "id": "cyberarkpas", - "description": "Collect logs from CyberArk Privileged Access Security with Elastic Agent.", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-cyberarkpas.audit-*", - "title": "CyberArk PAS audit logs" - }, - { - "dataset": "monitor", - "index_pattern": "logs-cyberarkpas.monitor-*", - "title": "CyberArk PAS monitor Events" - } - ], - "elser_embedding": "CyberArk Privileged Access Security - Collect logs from CyberArk Privileged Access Security with Elastic Agent. - CyberArk PAS audit logs CyberArk PAS monitor Events" - }, - { - "title": "Palo Alto Prisma Cloud", - "id": "prisma_cloud", - "description": "Collect logs from Prisma Cloud with Elastic Agent.", - "data_streams": [ - { - "dataset": "host_profile", - "index_pattern": "logs-prisma_cloud.host_profile-*", - "title": "Collect Host Profile logs from Prisma Cloud Workload Protection." - }, - { - "dataset": "host", - "index_pattern": "logs-prisma_cloud.host-*", - "title": "Collect Host logs from Prisma Cloud Workload Protection." - }, - { - "dataset": "audit", - "index_pattern": "logs-prisma_cloud.audit-*", - "title": "Collect Audit logs from Prisma Cloud Security Posture Management." - }, - { - "dataset": "alert", - "index_pattern": "logs-prisma_cloud.alert-*", - "title": "Collect Alert logs from Prisma Cloud Security Posture Management." - }, - { - "dataset": "incident_audit", - "index_pattern": "logs-prisma_cloud.incident_audit-*", - "title": "Collect Incident Audit logs from Prisma Cloud Workload Protection." - } - ], - "elser_embedding": "Palo Alto Prisma Cloud - Collect logs from Prisma Cloud with Elastic Agent. - Collect Host Profile logs from Prisma Cloud Workload Protection. Collect Host logs from Prisma Cloud Workload Protection. Collect Audit logs from Prisma Cloud Security Posture Management. Collect Alert logs from Prisma Cloud Security Posture Management. Collect Incident Audit logs from Prisma Cloud Workload Protection." - }, - { - "title": "Cilium Tetragon", - "id": "cilium_tetragon", - "description": "Collect Cilium Tetragon logs from Kubernetes environments.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-cilium_tetragon.log-*", - "title": "log\n" - } - ], - "elser_embedding": "Cilium Tetragon - Collect Cilium Tetragon logs from Kubernetes environments. - log\n" - }, - { - "title": "Qualys VMDR", - "id": "qualys_vmdr", - "description": "Collect data from Qualys VMDR platform with Elastic Agent.", - "data_streams": [ - { - "dataset": "knowledge_base", - "index_pattern": "logs-qualys_vmdr.knowledge_base-*", - "title": "Collect Knowledge Base data from Qualys VMDR platform." - }, - { - "dataset": "user_activity", - "index_pattern": "logs-qualys_vmdr.user_activity-*", - "title": "Collect User Activity Log data from Qualys VMDR platform." - }, - { - "dataset": "asset_host_detection", - "index_pattern": "logs-qualys_vmdr.asset_host_detection-*", - "title": "Collect Asset Host Detection data from Qualys VMDR platform." - } - ], - "elser_embedding": "Qualys VMDR - Collect data from Qualys VMDR platform with Elastic Agent. - Collect Knowledge Base data from Qualys VMDR platform. Collect User Activity Log data from Qualys VMDR platform. Collect Asset Host Detection data from Qualys VMDR platform." - }, - { - "title": "Elastic Agent", - "id": "elastic_agent", - "description": "Collect logs and metrics from Elastic Agents.", - "data_streams": [ - { - "dataset": "fleet_server_logs", - "index_pattern": "logs-elastic_agent.fleet_server_logs-*", - "title": "Elastic Agent" - }, - { - "dataset": "endpoint_security_metrics", - "index_pattern": "logs-elastic_agent.endpoint_security_metrics-*", - "title": "Elastic Agent" - }, - { - "dataset": "apm_server_logs", - "index_pattern": "logs-elastic_agent.apm_server_logs-*", - "title": "Elastic Agent" - }, - { - "dataset": "osquerybeat_logs", - "index_pattern": "logs-elastic_agent.osquerybeat_logs-*", - "title": "Elastic Agent" - }, - { - "dataset": "heartbeat_logs", - "index_pattern": "logs-elastic_agent.heartbeat_logs-*", - "title": "Elastic Agent" - }, - { - "dataset": "metricbeat_logs", - "index_pattern": "logs-elastic_agent.metricbeat_logs-*", - "title": "Elastic Agent" - }, - { - "dataset": "elastic_agent_metrics", - "index_pattern": "logs-elastic_agent.elastic_agent_metrics-*", - "title": "Elastic Agent" - }, - { - "dataset": "auditbeat_metrics", - "index_pattern": "logs-elastic_agent.auditbeat_metrics-*", - "title": "Elastic Agent Auditbeat Metrics" - }, - { - "dataset": "pf_elastic_symbolizer", - "index_pattern": "logs-elastic_agent.pf_elastic_symbolizer-*", - "title": "Elastic Agent" - }, - { - "dataset": "cloud_defend_logs", - "index_pattern": "logs-elastic_agent.cloud_defend_logs-*", - "title": "Elastic Agent" - }, - { - "dataset": "endpoint_sercurity_logs", - "index_pattern": "logs-elastic_agent.endpoint_sercurity_logs-*", - "title": "Elastic Agent" - }, - { - "dataset": "filebeat_input_metrics", - "index_pattern": "logs-elastic_agent.filebeat_input_metrics-*", - "title": "Elastic Agent" - }, - { - "dataset": "metricbeat_metrics", - "index_pattern": "logs-elastic_agent.metricbeat_metrics-*", - "title": "Elastic Agent" - }, - { - "dataset": "packetbeat_metrics", - "index_pattern": "logs-elastic_agent.packetbeat_metrics-*", - "title": "Elastic Agent" - }, - { - "dataset": "apm_server_metrics", - "index_pattern": "logs-elastic_agent.apm_server_metrics-*", - "title": "Elastic Agent" - }, - { - "dataset": "filebeat_input_logs", - "index_pattern": "logs-elastic_agent.filebeat_input_logs-*", - "title": "Elastic Agent" - }, - { - "dataset": "elastic_agent_logs", - "index_pattern": "logs-elastic_agent.elastic_agent_logs-*", - "title": "Elastic Agent" - }, - { - "dataset": "auditbeat_logs", - "index_pattern": "logs-elastic_agent.auditbeat_logs-*", - "title": "Elastic Agent" - }, - { - "dataset": "filebeat_logs", - "index_pattern": "logs-elastic_agent.filebeat_logs-*", - "title": "Elastic Agent" - }, - { - "dataset": "pf_host_agent_logs", - "index_pattern": "logs-elastic_agent.pf_host_agent_logs-*", - "title": "Elastic Agent" - }, - { - "dataset": "cloudbeat_logs", - "index_pattern": "logs-elastic_agent.cloudbeat_logs-*", - "title": "Elastic Agent" - }, - { - "dataset": "heartbeat_metrics", - "index_pattern": "logs-elastic_agent.heartbeat_metrics-*", - "title": "Elastic Agent" - }, - { - "dataset": "cloudbeat_metrics", - "index_pattern": "logs-elastic_agent.cloudbeat_metrics-*", - "title": "Elastic Agent" - }, - { - "dataset": "fleet_server_metrics", - "index_pattern": "logs-elastic_agent.fleet_server_metrics-*", - "title": "Elastic Agent" - }, - { - "dataset": "packetbeat_logs", - "index_pattern": "logs-elastic_agent.packetbeat_logs-*", - "title": "Elastic Agent" - }, - { - "dataset": "osquerybeat_metrics", - "index_pattern": "logs-elastic_agent.osquerybeat_metrics-*", - "title": "Elastic Agent" - }, - { - "dataset": "pf_elastic_collector", - "index_pattern": "logs-elastic_agent.pf_elastic_collector-*", - "title": "Elastic Agent" - }, - { - "dataset": "filebeat_metrics", - "index_pattern": "logs-elastic_agent.filebeat_metrics-*", - "title": "Elastic Agent" - } - ], - "elser_embedding": "Elastic Agent - Collect logs and metrics from Elastic Agents. - Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Auditbeat Metrics Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent Elastic Agent" - }, - { - "title": "Custom Filestream Logs", - "id": "filestream", - "description": "Collect log data using filestream with Elastic Agent.", - "data_streams": [ - { - "dataset": "generic", - "index_pattern": "logs-filestream.generic-*", - "title": "Custom Filestream Logs" - } - ], - "elser_embedding": "Custom Filestream Logs - Collect log data using filestream with Elastic Agent. - Custom Filestream Logs" - }, - { - "title": "OpenCanary", - "id": "opencanary", - "description": "This integration collects and parses logs from OpenCanary honeypots.", - "data_streams": [ - { - "dataset": "events", - "index_pattern": "logs-opencanary.events-*", - "title": "OpenCanary HoneyPot Events" - } - ], - "elser_embedding": "OpenCanary - This integration collects and parses logs from OpenCanary honeypots. - OpenCanary HoneyPot Events" - }, - { - "title": "Palo Alto Cortex XDR", - "id": "panw_cortex_xdr", - "description": "Collect logs from Palo Alto Cortex XDR with Elastic Agent.", - "data_streams": [ - { - "dataset": "incidents", - "index_pattern": "logs-panw_cortex_xdr.incidents-*", - "title": "Palo Alto Cortex XDR Incidents API" - }, - { - "dataset": "alerts", - "index_pattern": "logs-panw_cortex_xdr.alerts-*", - "title": "Palo Alto Cortex XDR Alerts API" - } - ], - "elser_embedding": "Palo Alto Cortex XDR - Collect logs from Palo Alto Cortex XDR with Elastic Agent. - Palo Alto Cortex XDR Incidents API Palo Alto Cortex XDR Alerts API" - }, - { - "title": "Cisco Nexus", - "id": "cisco_nexus", - "description": "Collect logs from Cisco Nexus with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-cisco_nexus.log-*", - "title": "Collect logs from Cisco Nexus" - } - ], - "elser_embedding": "Cisco Nexus - Collect logs from Cisco Nexus with Elastic Agent. - Collect logs from Cisco Nexus" - }, - { - "title": "JumpCloud", - "id": "jumpcloud", - "description": "Collect logs from JumpCloud Directory as a Service", - "data_streams": [ - { - "dataset": "events", - "index_pattern": "logs-jumpcloud.events-*", - "title": "JumpCloud Directory as a Service Events" - } - ], - "elser_embedding": "JumpCloud - Collect logs from JumpCloud Directory as a Service - JumpCloud Directory as a Service Events" - }, - { - "title": "Microsoft Defender for Endpoint", - "id": "microsoft_defender_endpoint", - "description": "Collect logs from Microsoft Defender for Endpoint with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-microsoft_defender_endpoint.log-*", - "title": "Microsoft Defender for Endpoint logs" - } - ], - "elser_embedding": "Microsoft Defender for Endpoint - Collect logs from Microsoft Defender for Endpoint with Elastic Agent. - Microsoft Defender for Endpoint logs" - }, - { - "title": "ActiveMQ", - "id": "activemq", - "description": "Collect logs and metrics from ActiveMQ instances with Elastic Agent.", - "data_streams": [ - { - "dataset": "broker", - "index_pattern": "logs-activemq.broker-*", - "title": "ActiveMQ broker metrics" - }, - { - "dataset": "queue", - "index_pattern": "logs-activemq.queue-*", - "title": "ActiveMQ queue metrics" - }, - { - "dataset": "audit", - "index_pattern": "logs-activemq.audit-*", - "title": "ActiveMQ audit logs" - }, - { - "dataset": "log", - "index_pattern": "logs-activemq.log-*", - "title": "ActiveMQ log logs" - }, - { - "dataset": "topic", - "index_pattern": "logs-activemq.topic-*", - "title": "ActiveMQ topic metrics" - } - ], - "elser_embedding": "ActiveMQ - Collect logs and metrics from ActiveMQ instances with Elastic Agent. - ActiveMQ broker metrics ActiveMQ queue metrics ActiveMQ audit logs ActiveMQ log logs ActiveMQ topic metrics" - }, - { - "title": "AbuseCH", - "id": "ti_abusech", - "description": "Ingest threat intelligence indicators from URL Haus, Malware Bazaar, and Threat Fox feeds with Elastic Agent.", - "data_streams": [ - { - "dataset": "threatfox", - "index_pattern": "logs-ti_abusech.threatfox-*", - "title": "AbuseCH Threat Fox indicators" - }, - { - "dataset": "url", - "index_pattern": "logs-ti_abusech.url-*", - "title": "AbuseCH URL logs" - }, - { - "dataset": "malware", - "index_pattern": "logs-ti_abusech.malware-*", - "title": "AbuseCH Malware payloads" - }, - { - "dataset": "malwarebazaar", - "index_pattern": "logs-ti_abusech.malwarebazaar-*", - "title": "AbuseCH MalwareBazaar payloads" - } - ], - "elser_embedding": "AbuseCH - Ingest threat intelligence indicators from URL Haus, Malware Bazaar, and Threat Fox feeds with Elastic Agent. - AbuseCH Threat Fox indicators AbuseCH URL logs AbuseCH Malware payloads AbuseCH MalwareBazaar payloads" - }, - { - "title": "Infoblox BloxOne DDI", - "id": "infoblox_bloxone_ddi", - "description": "Collect logs from Infoblox BloxOne DDI with Elastic Agent.", - "data_streams": [ - { - "dataset": "dns_data", - "index_pattern": "logs-infoblox_bloxone_ddi.dns_data-*", - "title": "Collect DNS Data logs from Infoblox BloxOne DDI" - }, - { - "dataset": "dns_config", - "index_pattern": "logs-infoblox_bloxone_ddi.dns_config-*", - "title": "Collect DNS Config logs from Infoblox BloxOne DDI" - }, - { - "dataset": "dhcp_lease", - "index_pattern": "logs-infoblox_bloxone_ddi.dhcp_lease-*", - "title": "Collect DHCP Lease logs from Infoblox BloxOne DDI" - } - ], - "elser_embedding": "Infoblox BloxOne DDI - Collect logs from Infoblox BloxOne DDI with Elastic Agent. - Collect DNS Data logs from Infoblox BloxOne DDI Collect DNS Config logs from Infoblox BloxOne DDI Collect DHCP Lease logs from Infoblox BloxOne DDI" - }, - { - "title": "Google Security Command Center", - "id": "google_scc", - "description": "Collect logs from Google Security Command Center with Elastic Agent.", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-google_scc.audit-*", - "title": "Collect Audit logs from Google Security Command Center." - }, - { - "dataset": "finding", - "index_pattern": "logs-google_scc.finding-*", - "title": "Collect Finding logs from Google Security Command Center." - }, - { - "dataset": "asset", - "index_pattern": "logs-google_scc.asset-*", - "title": "Collect Asset logs from Google Security Command Center." - }, - { - "dataset": "source", - "index_pattern": "logs-google_scc.source-*", - "title": "Collect Source logs from Google Security Command Center." - } - ], - "elser_embedding": "Google Security Command Center - Collect logs from Google Security Command Center with Elastic Agent. - Collect Audit logs from Google Security Command Center. Collect Finding logs from Google Security Command Center. Collect Asset logs from Google Security Command Center. Collect Source logs from Google Security Command Center." - }, - { - "title": "CoreDNS", - "id": "coredns", - "description": "Collect logs from CoreDNS instances with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-coredns.log-*", - "title": "CoreDNS logs" - } - ], - "elser_embedding": "CoreDNS - Collect logs from CoreDNS instances with Elastic Agent. - CoreDNS logs" - }, - { - "title": "NetFlow Records", - "id": "netflow", - "description": "Collect flow records from NetFlow and IPFIX exporters with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-netflow.log-*", - "title": "NetFlow logs" - } - ], - "elser_embedding": "NetFlow Records - Collect flow records from NetFlow and IPFIX exporters with Elastic Agent. - NetFlow logs" - }, - { - "title": "Forcepoint Web Security", - "id": "forcepoint_web", - "description": "Forcepoint Web Security", - "data_streams": [ - { - "dataset": "logs", - "index_pattern": "logs-forcepoint_web.logs-*", - "title": "Forcepoint Web Security Logs" - } - ], - "elser_embedding": "Forcepoint Web Security - Forcepoint Web Security - Forcepoint Web Security Logs" - }, - { - "title": "Trellix EDR Cloud", - "id": "trellix_edr_cloud", - "description": "Collect logs from Trellix EDR Cloud with Elastic Agent.", - "data_streams": [ - { - "dataset": "event", - "index_pattern": "logs-trellix_edr_cloud.event-*", - "title": "Collect Event logs from Trellix EDR Cloud." - } - ], - "elser_embedding": "Trellix EDR Cloud - Collect logs from Trellix EDR Cloud with Elastic Agent. - Collect Event logs from Trellix EDR Cloud." - }, - { - "title": "Slack Logs", - "id": "slack", - "description": "Slack Logs Integration", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-slack.audit-*", - "title": "Slack Audit Logs" - } - ], - "elser_embedding": "Slack Logs - Slack Logs Integration - Slack Audit Logs" - }, - { - "title": "Cisco FTD", - "id": "cisco_ftd", - "description": "Collect logs from Cisco FTD with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-cisco_ftd.log-*", - "title": "Cisco FTD logs" - } - ], - "elser_embedding": "Cisco FTD - Collect logs from Cisco FTD with Elastic Agent. - Cisco FTD logs" - }, - { - "title": "Microsoft DNS Server", - "id": "microsoft_dnsserver", - "description": "Collect logs from Microsoft DNS Server with Elastic Agent.", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-microsoft_dnsserver.audit-*", - "title": "Collect DNS Server Audit logs" - }, - { - "dataset": "analytical", - "index_pattern": "logs-microsoft_dnsserver.analytical-*", - "title": "Collect DNS Server Analytical logs" - } - ], - "elser_embedding": "Microsoft DNS Server - Collect logs from Microsoft DNS Server with Elastic Agent. - Collect DNS Server Audit logs Collect DNS Server Analytical logs" - }, - { - "title": "Mandiant Advantage", - "id": "ti_mandiant_advantage", - "description": "Collect Threat Intelligence from products within the Mandiant Advantage platform.", - "data_streams": [ - { - "dataset": "threat_intelligence", - "index_pattern": "logs-ti_mandiant_advantage.threat_intelligence-*", - "title": "Mandiant Threat Intelligence" - } - ], - "elser_embedding": "Mandiant Advantage - Collect Threat Intelligence from products within the Mandiant Advantage platform. - Mandiant Threat Intelligence" - }, - { - "title": "Fortinet FortiClient Logs", - "id": "fortinet_forticlient", - "description": "Collect logs from Fortinet FortiClient instances with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-fortinet_forticlient.log-*", - "title": "Fortinet FortiClient Endpoint Security logs" - } - ], - "elser_embedding": "Fortinet FortiClient Logs - Collect logs from Fortinet FortiClient instances with Elastic Agent. - Fortinet FortiClient Endpoint Security logs" - }, - { - "title": "AWS Fargate (for ECS clusters)", - "id": "awsfargate", - "description": "Collects metrics from containers and tasks running on Amazon ECS clusters with Elastic Agent.", - "data_streams": [ - { - "dataset": "task_stats", - "index_pattern": "logs-awsfargate.task_stats-*", - "title": "AWS Fargate task_stats metrics" - } - ], - "elser_embedding": "AWS Fargate (for ECS clusters) - Collects metrics from containers and tasks running on Amazon ECS clusters with Elastic Agent. - AWS Fargate task_stats metrics" - }, - { - "title": "Azure Network Watcher VNet", - "id": "azure_network_watcher_vnet", - "description": "Collect logs from Azure Network Watcher VNet with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-azure_network_watcher_vnet.log-*", - "title": "Collect VNet logs from Azure Network Watcher" - } - ], - "elser_embedding": "Azure Network Watcher VNet - Collect logs from Azure Network Watcher VNet with Elastic Agent. - Collect VNet logs from Azure Network Watcher" - }, - { - "title": "Osquery Logs", - "id": "osquery", - "description": "Collect logs from Osquery with Elastic Agent.", - "data_streams": [ - { - "dataset": "result", - "index_pattern": "logs-osquery.result-*", - "title": "Osquery result logs" - } - ], - "elser_embedding": "Osquery Logs - Collect logs from Osquery with Elastic Agent. - Osquery result logs" - }, - { - "title": "Pleasant Password Server", - "id": "pps", - "description": "Integration for Pleasant Password Server Syslog Messages", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-pps.log-*", - "title": "Pleasant Password Server logs" - } - ], - "elser_embedding": "Pleasant Password Server - Integration for Pleasant Password Server Syslog Messages - Pleasant Password Server logs" - }, - { - "title": "Bravura Monitor", - "id": "hid_bravura_monitor", - "description": "Collect logs from Bravura Security Fabric with Elastic Agent.", - "data_streams": [ - { - "dataset": "winlog", - "index_pattern": "logs-hid_bravura_monitor.winlog-*", - "title": "Bravura Security Fabric logs" - }, - { - "dataset": "log", - "index_pattern": "logs-hid_bravura_monitor.log-*", - "title": "Bravura Monitor" - } - ], - "elser_embedding": "Bravura Monitor - Collect logs from Bravura Security Fabric with Elastic Agent. - Bravura Security Fabric logs Bravura Monitor" - }, - { - "title": "MISP", - "id": "ti_misp", - "description": "Ingest threat intelligence indicators from MISP platform with Elastic Agent.", - "data_streams": [ - { - "dataset": "threat", - "index_pattern": "logs-ti_misp.threat-*", - "title": "MISP" - }, - { - "dataset": "threat_attributes", - "index_pattern": "logs-ti_misp.threat_attributes-*", - "title": "MISP" - } - ], - "elser_embedding": "MISP - Ingest threat intelligence indicators from MISP platform with Elastic Agent. - MISP MISP" - }, - { - "title": "Redis Enterprise", - "id": "redisenterprise", - "description": "Collect metrics from Redis Enterprise Cluster", - "data_streams": [ - { - "dataset": "node", - "index_pattern": "logs-redisenterprise.node-*", - "title": "node" - }, - { - "dataset": "proxy", - "index_pattern": "logs-redisenterprise.proxy-*", - "title": "proxy" - } - ], - "elser_embedding": "Redis Enterprise - Collect metrics from Redis Enterprise Cluster - node proxy" - }, - { - "title": "Network Packet Capture", - "id": "network_traffic", - "description": "Capture and analyze network traffic from a host with Elastic Agent.", - "data_streams": [ - { - "dataset": "nfs", - "index_pattern": "logs-network_traffic.nfs-*", - "title": "NFS" - }, - { - "dataset": "tls", - "index_pattern": "logs-network_traffic.tls-*", - "title": "TLS" - }, - { - "dataset": "icmp", - "index_pattern": "logs-network_traffic.icmp-*", - "title": "ICMP" - }, - { - "dataset": "cassandra", - "index_pattern": "logs-network_traffic.cassandra-*", - "title": "Cassandra" - }, - { - "dataset": "mongodb", - "index_pattern": "logs-network_traffic.mongodb-*", - "title": "MongoDB" - }, - { - "dataset": "thrift", - "index_pattern": "logs-network_traffic.thrift-*", - "title": "Thrift" - }, - { - "dataset": "flow", - "index_pattern": "logs-network_traffic.flow-*", - "title": "Flows" - }, - { - "dataset": "dhcpv4", - "index_pattern": "logs-network_traffic.dhcpv4-*", - "title": "DHCP" - }, - { - "dataset": "pgsql", - "index_pattern": "logs-network_traffic.pgsql-*", - "title": "PostgreSQL" - }, - { - "dataset": "redis", - "index_pattern": "logs-network_traffic.redis-*", - "title": "Redis" - }, - { - "dataset": "dns", - "index_pattern": "logs-network_traffic.dns-*", - "title": "DNS" - }, - { - "dataset": "sip", - "index_pattern": "logs-network_traffic.sip-*", - "title": "SIP" - }, - { - "dataset": "mysql", - "index_pattern": "logs-network_traffic.mysql-*", - "title": "MySQL" - }, - { - "dataset": "amqp", - "index_pattern": "logs-network_traffic.amqp-*", - "title": "AMQP" - }, - { - "dataset": "http", - "index_pattern": "logs-network_traffic.http-*", - "title": "HTTP" - }, - { - "dataset": "memcached", - "index_pattern": "logs-network_traffic.memcached-*", - "title": "Memcached" - } - ], - "elser_embedding": "Network Packet Capture - Capture and analyze network traffic from a host with Elastic Agent. - NFS TLS ICMP Cassandra MongoDB Thrift Flows DHCP PostgreSQL Redis DNS SIP MySQL AMQP HTTP Memcached" - }, - { - "title": "MySQL Enterprise", - "id": "mysql_enterprise", - "description": "Collect audit logs from MySQL Enterprise with Elastic Agent.", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-mysql_enterprise.audit-*", - "title": "MySQL Enterprise Audit Log" - } - ], - "elser_embedding": "MySQL Enterprise - Collect audit logs from MySQL Enterprise with Elastic Agent. - MySQL Enterprise Audit Log" - }, - { - "title": "GitHub", - "id": "github", - "description": "Collect logs from GitHub with Elastic Agent.", - "data_streams": [ - { - "dataset": "dependabot", - "index_pattern": "logs-github.dependabot-*", - "title": "GHAS Dependabot" - }, - { - "dataset": "issues", - "index_pattern": "logs-github.issues-*", - "title": "Github Issue" - }, - { - "dataset": "secret_scanning", - "index_pattern": "logs-github.secret_scanning-*", - "title": "GHAS Secret Scanning" - }, - { - "dataset": "audit", - "index_pattern": "logs-github.audit-*", - "title": "GitHub Audit Logs" - }, - { - "dataset": "code_scanning", - "index_pattern": "logs-github.code_scanning-*", - "title": "GHAS Code Scanning" - } - ], - "elser_embedding": "GitHub - Collect logs from GitHub with Elastic Agent. - GHAS Dependabot Github Issue GHAS Secret Scanning GitHub Audit Logs GHAS Code Scanning" - }, - { - "title": "Microsoft Entra ID Entity Analytics", - "id": "entityanalytics_entra_id", - "description": "Collect identities from Microsoft Entra ID (formerly Azure Active Directory) with Elastic Agent.", - "data_streams": [ - { - "dataset": "device", - "index_pattern": "logs-entityanalytics_entra_id.device-*", - "title": "Microsoft Entra ID Entity Analytics Device Events" - }, - { - "dataset": "user", - "index_pattern": "logs-entityanalytics_entra_id.user-*", - "title": "Microsoft Entra ID Entity Analytics User Events" - }, - { - "dataset": "entity", - "index_pattern": "logs-entityanalytics_entra_id.entity-*", - "title": "Identities" - } - ], - "elser_embedding": "Microsoft Entra ID Entity Analytics - Collect identities from Microsoft Entra ID (formerly Azure Active Directory) with Elastic Agent. - Microsoft Entra ID Entity Analytics Device Events Microsoft Entra ID Entity Analytics User Events Identities" - }, - { - "title": "ThreatConnect", - "id": "ti_threatconnect", - "description": "Collects Indicators from ThreatConnect using the Elastic Agent and saves them as logs inside Elastic", - "data_streams": [ - { - "dataset": "indicator", - "index_pattern": "logs-ti_threatconnect.indicator-*", - "title": "Collect Indicators from ThreatConnect." - } - ], - "elser_embedding": "ThreatConnect - Collects Indicators from ThreatConnect using the Elastic Agent and saves them as logs inside Elastic - Collect Indicators from ThreatConnect." - }, - { - "title": "Microsoft Sentinel", - "id": "microsoft_sentinel", - "description": "Collect logs from Microsoft Sentinel with Elastic Agent.", - "data_streams": [ - { - "dataset": "alert", - "index_pattern": "logs-microsoft_sentinel.alert-*", - "title": "Microsoft Sentinel Alert logs" - }, - { - "dataset": "incident", - "index_pattern": "logs-microsoft_sentinel.incident-*", - "title": "Microsoft Sentinel Incident logs" - }, - { - "dataset": "event", - "index_pattern": "logs-microsoft_sentinel.event-*", - "title": "Collect Events from Microsoft Sentinel." - } - ], - "elser_embedding": "Microsoft Sentinel - Collect logs from Microsoft Sentinel with Elastic Agent. - Microsoft Sentinel Alert logs Microsoft Sentinel Incident logs Collect Events from Microsoft Sentinel." - }, - { - "title": "Check Point", - "id": "checkpoint", - "description": "Collect logs from Check Point with Elastic Agent.", - "data_streams": [ - { - "dataset": "firewall", - "index_pattern": "logs-checkpoint.firewall-*", - "title": "Check Point firewall logs" - } - ], - "elser_embedding": "Check Point - Collect logs from Check Point with Elastic Agent. - Check Point firewall logs" - }, - { - "title": "WatchGuard Firebox", - "id": "watchguard_firebox", - "description": "Collect logs from WatchGuard Firebox with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-watchguard_firebox.log-*", - "title": "WatchGuard Firebox logs" - } - ], - "elser_embedding": "WatchGuard Firebox - Collect logs from WatchGuard Firebox with Elastic Agent. - WatchGuard Firebox logs" - }, - { - "title": "Nagios XI", - "id": "nagios_xi", - "description": "Collect Logs and Metrics from Nagios XI with Elastic Agent.", - "data_streams": [ - { - "dataset": "host", - "index_pattern": "logs-nagios_xi.host-*", - "title": "Host" - }, - { - "dataset": "events", - "index_pattern": "logs-nagios_xi.events-*", - "title": "Events" - }, - { - "dataset": "service", - "index_pattern": "logs-nagios_xi.service-*", - "title": "Service" - } - ], - "elser_embedding": "Nagios XI - Collect Logs and Metrics from Nagios XI with Elastic Agent. - Host Events Service" - }, - { - "title": "Atlassian Jira", - "id": "atlassian_jira", - "description": "Collect logs from Atlassian Jira with Elastic Agent.", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-atlassian_jira.audit-*", - "title": "Jira Audit Logs" - } - ], - "elser_embedding": "Atlassian Jira - Collect logs from Atlassian Jira with Elastic Agent. - Jira Audit Logs" - }, - { - "title": "Snyk", - "id": "snyk", - "description": "Collect logs from Snyk with Elastic Agent.", - "data_streams": [ - { - "dataset": "issues", - "index_pattern": "logs-snyk.issues-*", - "title": "Collect Snyk Issues Data" - }, - { - "dataset": "audit", - "index_pattern": "logs-snyk.audit-*", - "title": "Collect Snyk Audit Logs" - }, - { - "dataset": "audit_logs", - "index_pattern": "logs-snyk.audit_logs-*", - "title": "Collect Snyk Audit Logs" - }, - { - "dataset": "vulnerabilities", - "index_pattern": "logs-snyk.vulnerabilities-*", - "title": "Collect Snyk Vulnerability Data" - } - ], - "elser_embedding": "Snyk - Collect logs from Snyk with Elastic Agent. - Collect Snyk Issues Data Collect Snyk Audit Logs Collect Snyk Audit Logs Collect Snyk Vulnerability Data" - }, - { - "title": "Google Cloud Platform", - "id": "gcp", - "description": "Collect logs and metrics from Google Cloud Platform with Elastic Agent.", - "data_streams": [ - { - "dataset": "compute", - "index_pattern": "logs-gcp.compute-*", - "title": "GCP Compute Metrics" - }, - { - "dataset": "pubsub", - "index_pattern": "logs-gcp.pubsub-*", - "title": "GCP PubSub Metrics" - }, - { - "dataset": "cloudsql_postgresql", - "index_pattern": "logs-gcp.cloudsql_postgresql-*", - "title": "GCP CloudSQL PostgreSQL Metrics" - }, - { - "dataset": "billing", - "index_pattern": "logs-gcp.billing-*", - "title": "GCP Billing Metrics" - }, - { - "dataset": "loadbalancing_metrics", - "index_pattern": "logs-gcp.loadbalancing_metrics-*", - "title": "GCP Load Balancing Metrics" - }, - { - "dataset": "cloudrun_metrics", - "index_pattern": "logs-gcp.cloudrun_metrics-*", - "title": "GCP Cloud Run Metrics" - }, - { - "dataset": "audit", - "index_pattern": "logs-gcp.audit-*", - "title": "Google Cloud Platform (GCP) audit logs" - }, - { - "dataset": "dataproc", - "index_pattern": "logs-gcp.dataproc-*", - "title": "GCP Dataproc Metrics" - }, - { - "dataset": "redis", - "index_pattern": "logs-gcp.redis-*", - "title": "GCP Redis Metrics" - }, - { - "dataset": "cloudsql_mysql", - "index_pattern": "logs-gcp.cloudsql_mysql-*", - "title": "GCP CloudSQL MySQL Metrics" - }, - { - "dataset": "dns", - "index_pattern": "logs-gcp.dns-*", - "title": "Google Cloud Platform (GCP) DNS logs" - }, - { - "dataset": "cloudsql_sqlserver", - "index_pattern": "logs-gcp.cloudsql_sqlserver-*", - "title": "GCP CloudSQL SQL Server Metrics" - }, - { - "dataset": "storage", - "index_pattern": "logs-gcp.storage-*", - "title": "GCP Storage Metrics" - }, - { - "dataset": "gke", - "index_pattern": "logs-gcp.gke-*", - "title": "GCP GKE Metrics" - }, - { - "dataset": "vpcflow", - "index_pattern": "logs-gcp.vpcflow-*", - "title": "Google Cloud Platform (GCP) vpcflow logs" - }, - { - "dataset": "loadbalancing_logs", - "index_pattern": "logs-gcp.loadbalancing_logs-*", - "title": "Google Cloud Platform (GCP) Load Balancing logs" - }, - { - "dataset": "firestore", - "index_pattern": "logs-gcp.firestore-*", - "title": "GCP Firestore Metrics" - }, - { - "dataset": "firewall", - "index_pattern": "logs-gcp.firewall-*", - "title": "Google Cloud Platform (GCP) firewall logs" - } - ], - "elser_embedding": "Google Cloud Platform - Collect logs and metrics from Google Cloud Platform with Elastic Agent. - GCP Compute Metrics GCP PubSub Metrics GCP CloudSQL PostgreSQL Metrics GCP Billing Metrics GCP Load Balancing Metrics GCP Cloud Run Metrics Google Cloud Platform (GCP) audit logs GCP Dataproc Metrics GCP Redis Metrics GCP CloudSQL MySQL Metrics Google Cloud Platform (GCP) DNS logs GCP CloudSQL SQL Server Metrics GCP Storage Metrics GCP GKE Metrics Google Cloud Platform (GCP) vpcflow logs Google Cloud Platform (GCP) Load Balancing logs GCP Firestore Metrics Google Cloud Platform (GCP) firewall logs" - }, - { - "title": "Logstash", - "id": "logstash", - "description": "Collect logs and metrics from Logstash with Elastic Agent.", - "data_streams": [ - { - "dataset": "node_cel", - "index_pattern": "logs-logstash.node_cel-*", - "title": "Logstash Node Stats" - }, - { - "dataset": "pipeline", - "index_pattern": "logs-logstash.pipeline-*", - "title": "Logstash pipeline" - }, - { - "dataset": "plugins", - "index_pattern": "logs-logstash.plugins-*", - "title": "Logstash plugins" - }, - { - "dataset": "node_stats", - "index_pattern": "logs-logstash.node_stats-*", - "title": "Logstash node_stats metrics" - }, - { - "dataset": "slowlog", - "index_pattern": "logs-logstash.slowlog-*", - "title": "logstash slowlog logs" - }, - { - "dataset": "log", - "index_pattern": "logs-logstash.log-*", - "title": "Logstash logs" - }, - { - "dataset": "node", - "index_pattern": "logs-logstash.node-*", - "title": "Logstash node metrics" - } - ], - "elser_embedding": "Logstash - Collect logs and metrics from Logstash with Elastic Agent. - Logstash Node Stats Logstash pipeline Logstash plugins Logstash node_stats metrics logstash slowlog logs Logstash logs Logstash node metrics" - }, - { - "title": "Palo Alto Prisma Access", - "id": "prisma_access", - "description": "Collect logs from Palo Alto Prisma Access with Elastic Agent.", - "data_streams": [ - { - "dataset": "event", - "index_pattern": "logs-prisma_access.event-*", - "title": "Collect Events from Palo Alto Prisma Access" - } - ], - "elser_embedding": "Palo Alto Prisma Access - Collect logs from Palo Alto Prisma Access with Elastic Agent. - Collect Events from Palo Alto Prisma Access" - }, - { - "title": "Barracuda CloudGen Firewall Logs", - "id": "barracuda_cloudgen_firewall", - "description": "Collect logs from Barracuda CloudGen Firewall devices with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-barracuda_cloudgen_firewall.log-*", - "title": "Barracuda CloudGen Firewall Logs" - } - ], - "elser_embedding": "Barracuda CloudGen Firewall Logs - Collect logs from Barracuda CloudGen Firewall devices with Elastic Agent. - Barracuda CloudGen Firewall Logs" - }, - { - "title": "Jamf Pro", - "id": "jamf_pro", - "description": "Collect logs and inventory data from Jamf Pro with Elastic Agent", - "data_streams": [ - { - "dataset": "inventory", - "index_pattern": "logs-jamf_pro.inventory-*", - "title": "Inventory data" - }, - { - "dataset": "events", - "index_pattern": "logs-jamf_pro.events-*", - "title": "Jamf Pro Events" - } - ], - "elser_embedding": "Jamf Pro - Collect logs and inventory data from Jamf Pro with Elastic Agent - Inventory data Jamf Pro Events" - }, - { - "title": "Fortinet FortiManager Logs", - "id": "fortinet_fortimanager", - "description": "Collect logs from Fortinet FortiManager instances with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-fortinet_fortimanager.log-*", - "title": "Collect logs from Fortinet FortiManager" - } - ], - "elser_embedding": "Fortinet FortiManager Logs - Collect logs from Fortinet FortiManager instances with Elastic Agent. - Collect logs from Fortinet FortiManager" - }, - { - "title": "Elastic APM", - "id": "apm", - "description": "Monitor, detect, and diagnose complex application performance issues.", - "data_streams": [], - "elser_embedding": "Elastic APM - Monitor, detect, and diagnose complex application performance issues. - " - }, - { - "title": "AlienVault OTX", - "id": "ti_otx", - "description": "Ingest threat intelligence indicators from AlienVault Open Threat Exchange (OTX) with Elastic Agent.", - "data_streams": [ - { - "dataset": "pulses_subscribed", - "index_pattern": "logs-ti_otx.pulses_subscribed-*", - "title": "Alienvault OTX Subcribed Pulses" - }, - { - "dataset": "threat", - "index_pattern": "logs-ti_otx.threat-*", - "title": "Alienvault OTX logs" - } - ], - "elser_embedding": "AlienVault OTX - Ingest threat intelligence indicators from AlienVault Open Threat Exchange (OTX) with Elastic Agent. - Alienvault OTX Subcribed Pulses Alienvault OTX logs" - }, - { - "title": "Check Point", - "id": "checkpoint", - "description": "Collect logs from Check Point with Elastic Agent.", - "data_streams": [ - { - "dataset": "firewall", - "index_pattern": "logs-checkpoint.firewall-*", - "title": "Check Point firewall logs" - } - ], - "elser_embedding": "Check Point - Collect logs from Check Point with Elastic Agent. - Check Point firewall logs" - }, - { - "title": "Kubernetes OpenTelemetry Assets", - "id": "kubernetes_otel", - "description": "Utilise the pre-built dashboard for OTel-native metrics and events collected from a Kubernetes cluster", - "data_streams": [], - "elser_embedding": "Kubernetes OpenTelemetry Assets - Utilise the pre-built dashboard for OTel-native metrics and events collected from a Kubernetes cluster - " - }, - { - "title": "EclecticIQ", - "id": "ti_eclecticiq", - "description": "Ingest threat intelligence from EclecticIQ with Elastic Agent", - "data_streams": [ - { - "dataset": "threat", - "index_pattern": "logs-ti_eclecticiq.threat-*", - "title": "Poll Outgoing feed" - } - ], - "elser_embedding": "EclecticIQ - Ingest threat intelligence from EclecticIQ with Elastic Agent - Poll Outgoing feed" - }, - { - "title": "Lumos", - "id": "lumos", - "description": "An integration with Lumos to ship your Activity logs to your Elastic instance.", - "data_streams": [ - { - "dataset": "activity_logs", - "index_pattern": "logs-lumos.activity_logs-*", - "title": "Lumos Activity Logs" - } - ], - "elser_embedding": "Lumos - An integration with Lumos to ship your Activity logs to your Elastic instance. - Lumos Activity Logs" - }, - { - "title": "Anomali", - "id": "ti_anomali", - "description": "Ingest threat intelligence indicators from Anomali with Elastic Agent.", - "data_streams": [ - { - "dataset": "threatstream", - "index_pattern": "logs-ti_anomali.threatstream-*", - "title": "Anomali ThreatStream" - }, - { - "dataset": "intelligence", - "index_pattern": "logs-ti_anomali.intelligence-*", - "title": "Anomali ThreatStream" - } - ], - "elser_embedding": "Anomali - Ingest threat intelligence indicators from Anomali with Elastic Agent. - Anomali ThreatStream Anomali ThreatStream" - }, - { - "title": "Jolokia Input", - "id": "jolokia", - "description": "Collects Metrics from Jolokia Agents", - "data_streams": [], - "elser_embedding": "Jolokia Input - Collects Metrics from Jolokia Agents - " - }, - { - "title": "Sysdig", - "id": "sysdig", - "description": "Collect alerts from Sysdig using Elastic Agent.", - "data_streams": [ - { - "dataset": "alerts", - "index_pattern": "logs-sysdig.alerts-*", - "title": "Sysdig" - } - ], - "elser_embedding": "Sysdig - Collect alerts from Sysdig using Elastic Agent. - Sysdig" - }, - { - "title": "Pulse Connect Secure", - "id": "pulse_connect_secure", - "description": "Collect logs from Pulse Connect Secure with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-pulse_connect_secure.log-*", - "title": "Pulse Connect Secure" - } - ], - "elser_embedding": "Pulse Connect Secure - Collect logs from Pulse Connect Secure with Elastic Agent. - Pulse Connect Secure" - }, - { - "title": "Zeek", - "id": "zeek", - "description": "Collect logs from Zeek with Elastic Agent.", - "data_streams": [ - { - "dataset": "x509", - "index_pattern": "logs-zeek.x509-*", - "title": "Zeek x509 logs" - }, - { - "dataset": "software", - "index_pattern": "logs-zeek.software-*", - "title": "Zeek software logs" - }, - { - "dataset": "traceroute", - "index_pattern": "logs-zeek.traceroute-*", - "title": "Zeek traceroute logs" - }, - { - "dataset": "capture_loss", - "index_pattern": "logs-zeek.capture_loss-*", - "title": "Zeek capture_loss logs" - }, - { - "dataset": "smb_cmd", - "index_pattern": "logs-zeek.smb_cmd-*", - "title": "Zeek smb_cmd logs" - }, - { - "dataset": "snmp", - "index_pattern": "logs-zeek.snmp-*", - "title": "Zeek snmp logs" - }, - { - "dataset": "irc", - "index_pattern": "logs-zeek.irc-*", - "title": "Zeek irc logs" - }, - { - "dataset": "intel", - "index_pattern": "logs-zeek.intel-*", - "title": "Zeek intel logs" - }, - { - "dataset": "pe", - "index_pattern": "logs-zeek.pe-*", - "title": "Zeek pe logs" - }, - { - "dataset": "known_services", - "index_pattern": "logs-zeek.known_services-*", - "title": "Zeek Known Services logs" - }, - { - "dataset": "radius", - "index_pattern": "logs-zeek.radius-*", - "title": "Zeek radius logs" - }, - { - "dataset": "modbus", - "index_pattern": "logs-zeek.modbus-*", - "title": "Zeek modbus logs" - }, - { - "dataset": "tunnel", - "index_pattern": "logs-zeek.tunnel-*", - "title": "Zeek tunnel logs" - }, - { - "dataset": "stats", - "index_pattern": "logs-zeek.stats-*", - "title": "Zeek stats logs" - }, - { - "dataset": "smb_files", - "index_pattern": "logs-zeek.smb_files-*", - "title": "Zeek smb_files logs" - }, - { - "dataset": "ocsp", - "index_pattern": "logs-zeek.ocsp-*", - "title": "Zeek ocsp logs" - }, - { - "dataset": "connection", - "index_pattern": "logs-zeek.connection-*", - "title": "Zeek connection logs" - }, - { - "dataset": "kerberos", - "index_pattern": "logs-zeek.kerberos-*", - "title": "Zeek kerberos logs" - }, - { - "dataset": "weird", - "index_pattern": "logs-zeek.weird-*", - "title": "Zeek weird logs" - }, - { - "dataset": "smb_mapping", - "index_pattern": "logs-zeek.smb_mapping-*", - "title": "Zeek smb_mapping logs" - }, - { - "dataset": "signature", - "index_pattern": "logs-zeek.signature-*", - "title": "Zeek signature logs" - }, - { - "dataset": "ntp", - "index_pattern": "logs-zeek.ntp-*", - "title": "Zeek ntp logs" - }, - { - "dataset": "dns", - "index_pattern": "logs-zeek.dns-*", - "title": "Zeek dns logs" - }, - { - "dataset": "dpd", - "index_pattern": "logs-zeek.dpd-*", - "title": "Zeek dpd logs" - }, - { - "dataset": "dhcp", - "index_pattern": "logs-zeek.dhcp-*", - "title": "Zeek dhcp logs" - }, - { - "dataset": "notice", - "index_pattern": "logs-zeek.notice-*", - "title": "Zeek notice logs" - }, - { - "dataset": "files", - "index_pattern": "logs-zeek.files-*", - "title": "Zeek files logs" - }, - { - "dataset": "ntlm", - "index_pattern": "logs-zeek.ntlm-*", - "title": "Zeek ntlm logs" - }, - { - "dataset": "known_certs", - "index_pattern": "logs-zeek.known_certs-*", - "title": "Zeek Known Certs logs" - }, - { - "dataset": "sip", - "index_pattern": "logs-zeek.sip-*", - "title": "Zeek sip logs" - }, - { - "dataset": "rdp", - "index_pattern": "logs-zeek.rdp-*", - "title": "Zeek rdp logs" - }, - { - "dataset": "mysql", - "index_pattern": "logs-zeek.mysql-*", - "title": "Zeek mysql logs" - }, - { - "dataset": "rfb", - "index_pattern": "logs-zeek.rfb-*", - "title": "Zeek rfb logs" - }, - { - "dataset": "ssh", - "index_pattern": "logs-zeek.ssh-*", - "title": "Zeek ssh logs" - }, - { - "dataset": "syslog", - "index_pattern": "logs-zeek.syslog-*", - "title": "Zeek syslog logs" - }, - { - "dataset": "http", - "index_pattern": "logs-zeek.http-*", - "title": "Zeek http logs" - }, - { - "dataset": "ssl", - "index_pattern": "logs-zeek.ssl-*", - "title": "Zeek ssl logs" - }, - { - "dataset": "socks", - "index_pattern": "logs-zeek.socks-*", - "title": "Zeek socks logs" - }, - { - "dataset": "smtp", - "index_pattern": "logs-zeek.smtp-*", - "title": "Zeek smtp logs" - }, - { - "dataset": "ftp", - "index_pattern": "logs-zeek.ftp-*", - "title": "Zeek ftp logs" - }, - { - "dataset": "known_hosts", - "index_pattern": "logs-zeek.known_hosts-*", - "title": "Zeek Known Hosts logs" - }, - { - "dataset": "dnp3", - "index_pattern": "logs-zeek.dnp3-*", - "title": "Zeek dnp3 logs" - }, - { - "dataset": "dce_rpc", - "index_pattern": "logs-zeek.dce_rpc-*", - "title": "Zeek dce_rpc logs" - } - ], - "elser_embedding": "Zeek - Collect logs from Zeek with Elastic Agent. - Zeek x509 logs Zeek software logs Zeek traceroute logs Zeek capture_loss logs Zeek smb_cmd logs Zeek snmp logs Zeek irc logs Zeek intel logs Zeek pe logs Zeek Known Services logs Zeek radius logs Zeek modbus logs Zeek tunnel logs Zeek stats logs Zeek smb_files logs Zeek ocsp logs Zeek connection logs Zeek kerberos logs Zeek weird logs Zeek smb_mapping logs Zeek signature logs Zeek ntp logs Zeek dns logs Zeek dpd logs Zeek dhcp logs Zeek notice logs Zeek files logs Zeek ntlm logs Zeek Known Certs logs Zeek sip logs Zeek rdp logs Zeek mysql logs Zeek rfb logs Zeek ssh logs Zeek syslog logs Zeek http logs Zeek ssl logs Zeek socks logs Zeek smtp logs Zeek ftp logs Zeek Known Hosts logs Zeek dnp3 logs Zeek dce_rpc logs" - }, - { - "title": "CrowdStrike", - "id": "crowdstrike", - "description": "Collect logs from Crowdstrike with Elastic Agent.", - "data_streams": [ - { - "dataset": "fdr", - "index_pattern": "logs-crowdstrike.fdr-*", - "title": "Falcon Data Replicator" - }, - { - "dataset": "host", - "index_pattern": "logs-crowdstrike.host-*", - "title": "Collect Host logs from CrowdStrike." - }, - { - "dataset": "alert", - "index_pattern": "logs-crowdstrike.alert-*", - "title": "Collect Alert logs from CrowdStrike." - }, - { - "dataset": "falcon", - "index_pattern": "logs-crowdstrike.falcon-*", - "title": "Crowdstrike falcon logs" - } - ], - "elser_embedding": "CrowdStrike - Collect logs from Crowdstrike with Elastic Agent. - Falcon Data Replicator Collect Host logs from CrowdStrike. Collect Alert logs from CrowdStrike. Crowdstrike falcon logs" - }, - { - "title": "Fortinet FortiGate Firewall Logs", - "id": "fortinet_fortigate", - "description": "Collect logs from Fortinet FortiGate firewalls with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-fortinet_fortigate.log-*", - "title": "Fortinet FortiGate logs" - } - ], - "elser_embedding": "Fortinet FortiGate Firewall Logs - Collect logs from Fortinet FortiGate firewalls with Elastic Agent. - Fortinet FortiGate logs" - }, - { - "title": "Active Directory Entity Analytics", - "id": "entityanalytics_ad", - "description": "Collect User Identities from Active Directory Entity with Elastic Agent.", - "data_streams": [ - { - "dataset": "user", - "index_pattern": "logs-entityanalytics_ad.user-*", - "title": "Collect User Identities logs from Active Directory" - } - ], - "elser_embedding": "Active Directory Entity Analytics - Collect User Identities from Active Directory Entity with Elastic Agent. - Collect User Identities logs from Active Directory" - }, - { - "title": "Arista NG Firewall", - "id": "arista_ngfw", - "description": "Collect logs and metrics from Arista NG Firewall.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-arista_ngfw.log-*", - "title": "Firewall Event" - } - ], - "elser_embedding": "Arista NG Firewall - Collect logs and metrics from Arista NG Firewall. - Firewall Event" - }, - { - "title": "Proofpoint TAP", - "id": "proofpoint_tap", - "description": "Collect logs from Proofpoint TAP with Elastic Agent.", - "data_streams": [ - { - "dataset": "message_blocked", - "index_pattern": "logs-proofpoint_tap.message_blocked-*", - "title": "Message Blocked" - }, - { - "dataset": "clicks_blocked", - "index_pattern": "logs-proofpoint_tap.clicks_blocked-*", - "title": "Clicks Blocked" - }, - { - "dataset": "clicks_permitted", - "index_pattern": "logs-proofpoint_tap.clicks_permitted-*", - "title": "Clicks Permitted" - }, - { - "dataset": "message_delivered", - "index_pattern": "logs-proofpoint_tap.message_delivered-*", - "title": "Message Delivered" - } - ], - "elser_embedding": "Proofpoint TAP - Collect logs from Proofpoint TAP with Elastic Agent. - Message Blocked Clicks Blocked Clicks Permitted Message Delivered" - }, - { - "title": "BitDefender", - "id": "bitdefender", - "description": "Ingest BitDefender GravityZone logs and data", - "data_streams": [ - { - "dataset": "push_statistics", - "index_pattern": "logs-bitdefender.push_statistics-*", - "title": "BitDefender GravityZone Push Notification Statistics" - }, - { - "dataset": "push_configuration", - "index_pattern": "logs-bitdefender.push_configuration-*", - "title": "BitDefender GravityZone Push Notification Configuration" - }, - { - "dataset": "push_notifications", - "index_pattern": "logs-bitdefender.push_notifications-*", - "title": "BitDefender GravityZone Push Notifications" - } - ], - "elser_embedding": "BitDefender - Ingest BitDefender GravityZone logs and data - BitDefender GravityZone Push Notification Statistics BitDefender GravityZone Push Notification Configuration BitDefender GravityZone Push Notifications" - }, - { - "title": "Redis", - "id": "redis", - "description": "Collect logs and metrics from Redis servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "keyspace", - "index_pattern": "logs-redis.keyspace-*", - "title": "Redis keyspace metrics" - }, - { - "dataset": "key", - "index_pattern": "logs-redis.key-*", - "title": "Redis key metrics" - }, - { - "dataset": "info", - "index_pattern": "logs-redis.info-*", - "title": "Redis info metrics" - }, - { - "dataset": "slowlog", - "index_pattern": "logs-redis.slowlog-*", - "title": "Redis slow logs" - }, - { - "dataset": "log", - "index_pattern": "logs-redis.log-*", - "title": "Redis application logs" - } - ], - "elser_embedding": "Redis - Collect logs and metrics from Redis servers with Elastic Agent. - Redis keyspace metrics Redis key metrics Redis info metrics Redis slow logs Redis application logs" - }, - { - "title": "Cisco Duo", - "id": "cisco_duo", - "description": "Collect logs from Cisco Duo with Elastic Agent.", - "data_streams": [ - { - "dataset": "summary", - "index_pattern": "logs-cisco_duo.summary-*", - "title": "Cisco Duo summary logs" - }, - { - "dataset": "admin", - "index_pattern": "logs-cisco_duo.admin-*", - "title": "Cisco Duo administrator logs" - }, - { - "dataset": "telephony", - "index_pattern": "logs-cisco_duo.telephony-*", - "title": "Cisco Duo telephony logs (legacy)" - }, - { - "dataset": "telephony_v2", - "index_pattern": "logs-cisco_duo.telephony_v2-*", - "title": "Cisco Duo telephony logs" - }, - { - "dataset": "auth", - "index_pattern": "logs-cisco_duo.auth-*", - "title": "Cisco Duo authentication logs" - }, - { - "dataset": "trust_monitor", - "index_pattern": "logs-cisco_duo.trust_monitor-*", - "title": "Cisco Duo trust monitor logs" - }, - { - "dataset": "activity", - "index_pattern": "logs-cisco_duo.activity-*", - "title": "Cisco Duo activity logs" - }, - { - "dataset": "offline_enrollment", - "index_pattern": "logs-cisco_duo.offline_enrollment-*", - "title": "Cisco Duo offline enrollment logs" - } - ], - "elser_embedding": "Cisco Duo - Collect logs from Cisco Duo with Elastic Agent. - Cisco Duo summary logs Cisco Duo administrator logs Cisco Duo telephony logs (legacy) Cisco Duo telephony logs Cisco Duo authentication logs Cisco Duo trust monitor logs Cisco Duo activity logs Cisco Duo offline enrollment logs" - }, - { - "title": "Elasticsearch", - "id": "elasticsearch", - "description": "Elasticsearch Integration", - "data_streams": [ - { - "dataset": "index_recovery", - "index_pattern": "logs-elasticsearch.index_recovery-*", - "title": "Elasticsearch index_recovery metrics" - }, - { - "dataset": "shard", - "index_pattern": "logs-elasticsearch.shard-*", - "title": "Elasticsearch shard metrics" - }, - { - "dataset": "ingest_pipeline", - "index_pattern": "logs-elasticsearch.ingest_pipeline-*", - "title": "Elasticsearch ingest metrics" - }, - { - "dataset": "enrich", - "index_pattern": "logs-elasticsearch.enrich-*", - "title": "Elasticsearch enrich metrics" - }, - { - "dataset": "audit", - "index_pattern": "logs-elasticsearch.audit-*", - "title": "Elasticsearch audit logs" - }, - { - "dataset": "server", - "index_pattern": "logs-elasticsearch.server-*", - "title": "Elasticsearch server logs" - }, - { - "dataset": "node_stats", - "index_pattern": "logs-elasticsearch.node_stats-*", - "title": "Elasticsearch node_stats metrics" - }, - { - "dataset": "index_summary", - "index_pattern": "logs-elasticsearch.index_summary-*", - "title": "Elasticsearch index_summary metrics" - }, - { - "dataset": "deprecation", - "index_pattern": "logs-elasticsearch.deprecation-*", - "title": "Elasticsearch deprecation logs" - }, - { - "dataset": "index", - "index_pattern": "logs-elasticsearch.index-*", - "title": "Elasticsearch index metrics" - }, - { - "dataset": "slowlog", - "index_pattern": "logs-elasticsearch.slowlog-*", - "title": "Elasticsearch slowlog logs" - }, - { - "dataset": "pending_tasks", - "index_pattern": "logs-elasticsearch.pending_tasks-*", - "title": "Elasticsearch pending_tasks metrics" - }, - { - "dataset": "ccr", - "index_pattern": "logs-elasticsearch.ccr-*", - "title": "Elasticsearch ccr metrics" - }, - { - "dataset": "node", - "index_pattern": "logs-elasticsearch.node-*", - "title": "Elasticsearch node metrics" - }, - { - "dataset": "cluster_stats", - "index_pattern": "logs-elasticsearch.cluster_stats-*", - "title": "Elasticsearch cluster_stats metrics" - }, - { - "dataset": "gc", - "index_pattern": "logs-elasticsearch.gc-*", - "title": "Elasticsearch gc logs" - }, - { - "dataset": "ml_job", - "index_pattern": "logs-elasticsearch.ml_job-*", - "title": "Elasticsearch ml_job metrics" - } - ], - "elser_embedding": "Elasticsearch - Elasticsearch Integration - Elasticsearch index_recovery metrics Elasticsearch shard metrics Elasticsearch ingest metrics Elasticsearch enrich metrics Elasticsearch audit logs Elasticsearch server logs Elasticsearch node_stats metrics Elasticsearch index_summary metrics Elasticsearch deprecation logs Elasticsearch index metrics Elasticsearch slowlog logs Elasticsearch pending_tasks metrics Elasticsearch ccr metrics Elasticsearch node metrics Elasticsearch cluster_stats metrics Elasticsearch gc logs Elasticsearch ml_job metrics" - }, - { - "title": "Universal Profiling Agent", - "id": "profiler_agent", - "description": "Fleet-wide, whole-system, continuous profiling with zero instrumentation.", - "data_streams": [], - "elser_embedding": "Universal Profiling Agent - Fleet-wide, whole-system, continuous profiling with zero instrumentation. - " - }, - { - "title": "Check Point Harmony Email & Collaboration", - "id": "checkpoint_email", - "description": "Collect logs from Check Point Harmony Email & Collaboration with Elastic Agent.", - "data_streams": [ - { - "dataset": "event", - "index_pattern": "logs-checkpoint_email.event-*", - "title": "Check Point Harmony Email & Collaboration Event logs" - } - ], - "elser_embedding": "Check Point Harmony Email & Collaboration - Collect logs from Check Point Harmony Email & Collaboration with Elastic Agent. - Check Point Harmony Email & Collaboration Event logs" - }, - { - "title": "Apache HTTP Server", - "id": "apache", - "description": "Collect logs and metrics from Apache servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "access", - "index_pattern": "logs-apache.access-*", - "title": "Apache access logs" - }, - { - "dataset": "error", - "index_pattern": "logs-apache.error-*", - "title": "Apache error logs" - }, - { - "dataset": "status", - "index_pattern": "logs-apache.status-*", - "title": "Apache status metrics" - } - ], - "elser_embedding": "Apache HTTP Server - Collect logs and metrics from Apache servers with Elastic Agent. - Apache access logs Apache error logs Apache status metrics" - }, - { - "title": "Istio", - "id": "istio", - "description": "Collect logs and metrics from the service mesh Istio with Elastic Agent.", - "data_streams": [ - { - "dataset": "access_logs", - "index_pattern": "logs-istio.access_logs-*", - "title": "Istio access logs" - }, - { - "dataset": "proxy_metrics", - "index_pattern": "logs-istio.proxy_metrics-*", - "title": "Istio Proxy Metrics" - }, - { - "dataset": "istiod_metrics", - "index_pattern": "logs-istio.istiod_metrics-*", - "title": "Istiod Metrics" - } - ], - "elser_embedding": "Istio - Collect logs and metrics from the service mesh Istio with Elastic Agent. - Istio access logs Istio Proxy Metrics Istiod Metrics" - }, - { - "title": "GCP Metrics Input", - "id": "gcp_metrics", - "description": "GCP Metrics Input", - "data_streams": [], - "elser_embedding": "GCP Metrics Input - GCP Metrics Input - " - }, - { - "title": "Fortinet FortiMail", - "id": "fortinet_fortimail", - "description": "Collect logs from Fortinet FortiMail instances with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-fortinet_fortimail.log-*", - "title": "Collect logs from Fortinet FortiMail" - } - ], - "elser_embedding": "Fortinet FortiMail - Collect logs from Fortinet FortiMail instances with Elastic Agent. - Collect logs from Fortinet FortiMail" - }, - { - "title": "Spring Boot", - "id": "spring_boot", - "description": "This Elastic integration collects logs and metrics from Spring Boot integration.", - "data_streams": [ - { - "dataset": "memory", - "index_pattern": "logs-spring_boot.memory-*", - "title": "Memory Metrics" - }, - { - "dataset": "http_trace", - "index_pattern": "logs-spring_boot.http_trace-*", - "title": "HTTP Trace Metrics" - }, - { - "dataset": "gc", - "index_pattern": "logs-spring_boot.gc-*", - "title": "Garbage Collector (GC) Metrics" - }, - { - "dataset": "threading", - "index_pattern": "logs-spring_boot.threading-*", - "title": "Threading Metrics" - }, - { - "dataset": "audit_events", - "index_pattern": "logs-spring_boot.audit_events-*", - "title": "Audit Events" - } - ], - "elser_embedding": "Spring Boot - This Elastic integration collects logs and metrics from Spring Boot integration. - Memory Metrics HTTP Trace Metrics Garbage Collector (GC) Metrics Threading Metrics Audit Events" - }, - { - "title": "Jamf Compliance Reporter", - "id": "jamf_compliance_reporter", - "description": "Collect logs from Jamf Compliance Reporter with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-jamf_compliance_reporter.log-*", - "title": "Jamf Compliance Reporter logs" - } - ], - "elser_embedding": "Jamf Compliance Reporter - Collect logs from Jamf Compliance Reporter with Elastic Agent. - Jamf Compliance Reporter logs" - }, - { - "title": "SentinelOne", - "id": "sentinel_one", - "description": "Collect logs from SentinelOne with Elastic Agent.", - "data_streams": [ - { - "dataset": "group", - "index_pattern": "logs-sentinel_one.group-*", - "title": "Collect Group logs from SentinelOne" - }, - { - "dataset": "threat", - "index_pattern": "logs-sentinel_one.threat-*", - "title": "Collect Threat logs from SentinelOne" - }, - { - "dataset": "alert", - "index_pattern": "logs-sentinel_one.alert-*", - "title": "Collect Alert logs from SentinelOne" - }, - { - "dataset": "agent", - "index_pattern": "logs-sentinel_one.agent-*", - "title": "Collect Agent logs from SentinelOne" - }, - { - "dataset": "activity", - "index_pattern": "logs-sentinel_one.activity-*", - "title": "Collect Activity logs from SentinelOne" - } - ], - "elser_embedding": "SentinelOne - Collect logs from SentinelOne with Elastic Agent. - Collect Group logs from SentinelOne Collect Threat logs from SentinelOne Collect Alert logs from SentinelOne Collect Agent logs from SentinelOne Collect Activity logs from SentinelOne" - }, - { - "title": "Enterprise Search", - "id": "enterprisesearch", - "description": "Enterprise Search Integration", - "data_streams": [ - { - "dataset": "stats", - "index_pattern": "logs-enterprisesearch.stats-*", - "title": "Enterprise Search stats metrics" - }, - { - "dataset": "health", - "index_pattern": "logs-enterprisesearch.health-*", - "title": "Enterprise Search health metrics" - } - ], - "elser_embedding": "Enterprise Search - Enterprise Search Integration - Enterprise Search stats metrics Enterprise Search health metrics" - }, - { - "title": "Microsoft Exchange Online Message Trace", - "id": "microsoft_exchange_online_message_trace", - "description": "Microsoft Exchange Online Message Trace Integration", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-microsoft_exchange_online_message_trace.log-*", - "title": "Microsoft Exchange Online Message Trace logs" - } - ], - "elser_embedding": "Microsoft Exchange Online Message Trace - Microsoft Exchange Online Message Trace Integration - Microsoft Exchange Online Message Trace logs" - }, - { - "title": "CrowdStrike Falcon Intelligence", - "id": "ti_crowdstrike", - "description": "Collect logs from CrowdStrike Falcon Intelligence with Elastic Agent.", - "data_streams": [ - { - "dataset": "intel", - "index_pattern": "logs-ti_crowdstrike.intel-*", - "title": "Collect Intel logs from CrowdStrike Falcon Intelligence." - }, - { - "dataset": "ioc", - "index_pattern": "logs-ti_crowdstrike.ioc-*", - "title": "Collect IOC logs from CrowdStrike Falcon Intelligence." - } - ], - "elser_embedding": "CrowdStrike Falcon Intelligence - Collect logs from CrowdStrike Falcon Intelligence with Elastic Agent. - Collect Intel logs from CrowdStrike Falcon Intelligence. Collect IOC logs from CrowdStrike Falcon Intelligence." - }, - { - "title": "Auditd Manager", - "id": "auditd_manager", - "description": "The Auditd Manager Integration receives audit events from the Linux Audit Framework that is a part of the Linux kernel.", - "data_streams": [ - { - "dataset": "auditd", - "index_pattern": "logs-auditd_manager.auditd-*", - "title": "Auditd Manager" - } - ], - "elser_embedding": "Auditd Manager - The Auditd Manager Integration receives audit events from the Linux Audit Framework that is a part of the Linux kernel. - Auditd Manager" - }, - { - "title": "Oracle", - "id": "oracle", - "description": "Collect Oracle Audit Log, Performance metrics, Tablespace metrics, Sysmetrics metrics, System statistics metrics, memory metrics from Oracle database.", - "data_streams": [ - { - "dataset": "memory", - "index_pattern": "logs-oracle.memory-*", - "title": "Memory metrics" - }, - { - "dataset": "performance", - "index_pattern": "logs-oracle.performance-*", - "title": "Oracle performance metrics" - }, - { - "dataset": "database_audit", - "index_pattern": "logs-oracle.database_audit-*", - "title": "Oracle Audit Log" - }, - { - "dataset": "sysmetric", - "index_pattern": "logs-oracle.sysmetric-*", - "title": "Sysmetric related metrics." - }, - { - "dataset": "system_statistics", - "index_pattern": "logs-oracle.system_statistics-*", - "title": "System Statistics" - }, - { - "dataset": "tablespace", - "index_pattern": "logs-oracle.tablespace-*", - "title": "Oracle tablespace metrics" - } - ], - "elser_embedding": "Oracle - Collect Oracle Audit Log, Performance metrics, Tablespace metrics, Sysmetrics metrics, System statistics metrics, memory metrics from Oracle database. - Memory metrics Oracle performance metrics Oracle Audit Log Sysmetric related metrics. System Statistics Oracle tablespace metrics" - }, - { - "title": "Akamai", - "id": "akamai", - "description": "Collect logs from Akamai with Elastic Agent.", - "data_streams": [ - { - "dataset": "siem", - "index_pattern": "logs-akamai.siem-*", - "title": "Akamai SIEM Logs" - } - ], - "elser_embedding": "Akamai - Collect logs from Akamai with Elastic Agent. - Akamai SIEM Logs" - }, - { - "title": "Custom Journald logs", - "id": "journald", - "description": "Collect logs from journald with Elastic Agent.", - "data_streams": [], - "elser_embedding": "Custom Journald logs - Collect logs from journald with Elastic Agent. - " - }, - { - "title": "Universal Profiling Collector", - "id": "profiler_collector", - "description": "Fleet-wide, whole-system, continuous profiling with zero instrumentation.", - "data_streams": [], - "elser_embedding": "Universal Profiling Collector - Fleet-wide, whole-system, continuous profiling with zero instrumentation. - " - }, - { - "title": "Custom API using Common Expression Language", - "id": "cel", - "description": "Collect custom events from an API with Elastic agent", - "data_streams": [], - "elser_embedding": "Custom API using Common Expression Language - Collect custom events from an API with Elastic agent - " - }, - { - "title": "etcd", - "id": "etcd", - "description": "Collect metrics from etcd instances with Elastic Agent.", - "data_streams": [ - { - "dataset": "self", - "index_pattern": "logs-etcd.self-*", - "title": "etcd self metrics" - }, - { - "dataset": "leader", - "index_pattern": "logs-etcd.leader-*", - "title": "etcd leader metrics" - }, - { - "dataset": "store", - "index_pattern": "logs-etcd.store-*", - "title": "etcd store metrics" - }, - { - "dataset": "metrics", - "index_pattern": "logs-etcd.metrics-*", - "title": "etcd v3 metrics" - } - ], - "elser_embedding": "etcd - Collect metrics from etcd instances with Elastic Agent. - etcd self metrics etcd leader metrics etcd store metrics etcd v3 metrics" - }, - { - "title": "Citrix Web App Firewall", - "id": "citrix_waf", - "description": "Ingest events from Citrix Systems Web App Firewall.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-citrix_waf.log-*", - "title": "Cisco ASA logs" - } - ], - "elser_embedding": "Citrix Web App Firewall - Ingest events from Citrix Systems Web App Firewall. - Cisco ASA logs" - }, - { - "title": "Azure OpenAI", - "id": "azure_openai", - "description": "Collects Azure OpenAI Logs and Metrics", - "data_streams": [ - { - "dataset": "logs", - "index_pattern": "logs-azure_openai.logs-*", - "title": "Collect Azure OpenAI logs" - }, - { - "dataset": "metrics", - "index_pattern": "logs-azure_openai.metrics-*", - "title": "Collect OpenAI metrics" - } - ], - "elser_embedding": "Azure OpenAI - Collects Azure OpenAI Logs and Metrics - Collect Azure OpenAI logs Collect OpenAI metrics" - }, - { - "title": "Cisco ISE", - "id": "cisco_ise", - "description": "Collect logs from Cisco ISE with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-cisco_ise.log-*", - "title": "Cisco ISE logs" - } - ], - "elser_embedding": "Cisco ISE - Collect logs from Cisco ISE with Elastic Agent. - Cisco ISE logs" - }, - { - "title": "Citrix ADC", - "id": "citrix_adc", - "description": "This Elastic integration collects logs and metrics from Citrix ADC product.", - "data_streams": [ - { - "dataset": "vpn", - "index_pattern": "logs-citrix_adc.vpn-*", - "title": "VPN metrics" - }, - { - "dataset": "log", - "index_pattern": "logs-citrix_adc.log-*", - "title": "Citrix ADC logs" - }, - { - "dataset": "service", - "index_pattern": "logs-citrix_adc.service-*", - "title": "Citrix ADC Service metrics" - }, - { - "dataset": "system", - "index_pattern": "logs-citrix_adc.system-*", - "title": "System metrics" - }, - { - "dataset": "interface", - "index_pattern": "logs-citrix_adc.interface-*", - "title": "Interface metrics" - }, - { - "dataset": "lbvserver", - "index_pattern": "logs-citrix_adc.lbvserver-*", - "title": "Load Balancing Virtual Server metrics" - } - ], - "elser_embedding": "Citrix ADC - This Elastic integration collects logs and metrics from Citrix ADC product. - VPN metrics Citrix ADC logs Citrix ADC Service metrics System metrics Interface metrics Load Balancing Virtual Server metrics" - }, - { - "title": "Box Events", - "id": "box_events", - "description": "Collect logs from Box with Elastic Agent", - "data_streams": [ - { - "dataset": "events", - "index_pattern": "logs-box_events.events-*", - "title": "List user and enterprise events" - } - ], - "elser_embedding": "Box Events - Collect logs from Box with Elastic Agent - List user and enterprise events" - }, - { - "title": "Prometheus", - "id": "prometheus", - "description": "Collect metrics from Prometheus servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "query", - "index_pattern": "logs-prometheus.query-*", - "title": "Prometheus query metrics" - }, - { - "dataset": "remote_write", - "index_pattern": "logs-prometheus.remote_write-*", - "title": "Prometheus remote_write metrics" - }, - { - "dataset": "collector", - "index_pattern": "logs-prometheus.collector-*", - "title": "Prometheus collector metrics" - } - ], - "elser_embedding": "Prometheus - Collect metrics from Prometheus servers with Elastic Agent. - Prometheus query metrics Prometheus remote_write metrics Prometheus collector metrics" - }, - { - "title": "Kubernetes", - "id": "kubernetes", - "description": "Collect logs and metrics from Kubernetes clusters with Elastic Agent.", - "data_streams": [ - { - "dataset": "state_resourcequota", - "index_pattern": "logs-kubernetes.state_resourcequota-*", - "title": "Kubernetes ResourceQuota metrics" - }, - { - "dataset": "state_storageclass", - "index_pattern": "logs-kubernetes.state_storageclass-*", - "title": "Kubernetes StorageClass metrics" - }, - { - "dataset": "state_persistentvolume", - "index_pattern": "logs-kubernetes.state_persistentvolume-*", - "title": "Kubernetes PersistentVolume metrics" - }, - { - "dataset": "pod", - "index_pattern": "logs-kubernetes.pod-*", - "title": "Kubernetes Pod metrics" - }, - { - "dataset": "state_container", - "index_pattern": "logs-kubernetes.state_container-*", - "title": "Kubernetes Container metrics" - }, - { - "dataset": "state_service", - "index_pattern": "logs-kubernetes.state_service-*", - "title": "Kubernetes Service metrics" - }, - { - "dataset": "state_replicaset", - "index_pattern": "logs-kubernetes.state_replicaset-*", - "title": "Kubernetes state_replicaset metrics" - }, - { - "dataset": "state_deployment", - "index_pattern": "logs-kubernetes.state_deployment-*", - "title": "Kubernetes Deployment metrics" - }, - { - "dataset": "container", - "index_pattern": "logs-kubernetes.container-*", - "title": "Kubernetes Container metrics" - }, - { - "dataset": "state_cronjob", - "index_pattern": "logs-kubernetes.state_cronjob-*", - "title": "Kubernetes Cronjob metrics" - }, - { - "dataset": "state_persistentvolumeclaim", - "index_pattern": "logs-kubernetes.state_persistentvolumeclaim-*", - "title": "Kubernetes PersistentVolumeClaim metrics" - }, - { - "dataset": "apiserver", - "index_pattern": "logs-kubernetes.apiserver-*", - "title": "Kubernetes API Server metrics" - }, - { - "dataset": "audit_logs", - "index_pattern": "logs-kubernetes.audit_logs-*", - "title": "Kubernetes audit logs" - }, - { - "dataset": "container_logs", - "index_pattern": "logs-kubernetes.container_logs-*", - "title": "Kubernetes container logs" - }, - { - "dataset": "state_namespace", - "index_pattern": "logs-kubernetes.state_namespace-*", - "title": "Kubernetes Namespace metrics" - }, - { - "dataset": "controllermanager", - "index_pattern": "logs-kubernetes.controllermanager-*", - "title": "Kubernetes Controller Manager metrics" - }, - { - "dataset": "state_statefulset", - "index_pattern": "logs-kubernetes.state_statefulset-*", - "title": "Kubernetes StatefulSet metrics" - }, - { - "dataset": "state_pod", - "index_pattern": "logs-kubernetes.state_pod-*", - "title": "Kubernetes Pod metrics" - }, - { - "dataset": "event", - "index_pattern": "logs-kubernetes.event-*", - "title": "Kubernetes Event metrics" - }, - { - "dataset": "node", - "index_pattern": "logs-kubernetes.node-*", - "title": "Kubernetes Node metrics" - }, - { - "dataset": "scheduler", - "index_pattern": "logs-kubernetes.scheduler-*", - "title": "Kubernetes Scheduler metrics" - }, - { - "dataset": "system", - "index_pattern": "logs-kubernetes.system-*", - "title": "Kubernetes System metrics" - }, - { - "dataset": "proxy", - "index_pattern": "logs-kubernetes.proxy-*", - "title": "Kubernetes Proxy metrics" - }, - { - "dataset": "state_node", - "index_pattern": "logs-kubernetes.state_node-*", - "title": "Kubernetes Node metrics" - }, - { - "dataset": "volume", - "index_pattern": "logs-kubernetes.volume-*", - "title": "Kubernetes Volume metrics" - }, - { - "dataset": "state_job", - "index_pattern": "logs-kubernetes.state_job-*", - "title": "Kubernetes Job metrics" - }, - { - "dataset": "state_daemonset", - "index_pattern": "logs-kubernetes.state_daemonset-*", - "title": "Kubernetes Deamonset metrics" - } - ], - "elser_embedding": "Kubernetes - Collect logs and metrics from Kubernetes clusters with Elastic Agent. - Kubernetes ResourceQuota metrics Kubernetes StorageClass metrics Kubernetes PersistentVolume metrics Kubernetes Pod metrics Kubernetes Container metrics Kubernetes Service metrics Kubernetes state_replicaset metrics Kubernetes Deployment metrics Kubernetes Container metrics Kubernetes Cronjob metrics Kubernetes PersistentVolumeClaim metrics Kubernetes API Server metrics Kubernetes audit logs Kubernetes container logs Kubernetes Namespace metrics Kubernetes Controller Manager metrics Kubernetes StatefulSet metrics Kubernetes Pod metrics Kubernetes Event metrics Kubernetes Node metrics Kubernetes Scheduler metrics Kubernetes System metrics Kubernetes Proxy metrics Kubernetes Node metrics Kubernetes Volume metrics Kubernetes Job metrics Kubernetes Deamonset metrics" - }, - { - "title": "Okta Entity Analytics", - "id": "entityanalytics_okta", - "description": "Collect User Identities from Okta with Elastic Agent.", - "data_streams": [ - { - "dataset": "user", - "index_pattern": "logs-entityanalytics_okta.user-*", - "title": "Collect User Identities logs from Okta" - } - ], - "elser_embedding": "Okta Entity Analytics - Collect User Identities from Okta with Elastic Agent. - Collect User Identities logs from Okta" - }, - { - "title": "GCP Vertex AI", - "id": "gcp_vertexai", - "description": "Collect GCP Vertex AI metrics with Elastic Agent", - "data_streams": [ - { - "dataset": "metrics", - "index_pattern": "logs-gcp_vertexai.metrics-*", - "title": "GCP Vertex AI Metrics" - } - ], - "elser_embedding": "GCP Vertex AI - Collect GCP Vertex AI metrics with Elastic Agent - GCP Vertex AI Metrics" - }, - { - "title": "First EPSS", - "id": "first_epss", - "description": "Collect exploit prediction score data from the First EPSS API with Elastic Agent.", - "data_streams": [ - { - "dataset": "vulnerability", - "index_pattern": "logs-first_epss.vulnerability-*", - "title": "Collect EPSS data from First API." - } - ], - "elser_embedding": "First EPSS - Collect exploit prediction score data from the First EPSS API with Elastic Agent. - Collect EPSS data from First API." - }, - { - "title": "Snort", - "id": "snort", - "description": "Collect logs from Snort with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-snort.log-*", - "title": "Snort" - } - ], - "elser_embedding": "Snort - Collect logs from Snort with Elastic Agent. - Snort" - }, - { - "title": "Azure Functions", - "id": "azure_functions", - "description": "Get metrics and logs from Azure Functions", - "data_streams": [ - { - "dataset": "functionapplogs", - "index_pattern": "logs-azure_functions.functionapplogs-*", - "title": "Collect Azure Functions logs" - }, - { - "dataset": "metrics", - "index_pattern": "logs-azure_functions.metrics-*", - "title": "Azure Functions App Metrics" - } - ], - "elser_embedding": "Azure Functions - Get metrics and logs from Azure Functions - Collect Azure Functions logs Azure Functions App Metrics" - }, - { - "title": "SentinelOne Cloud Funnel", - "id": "sentinel_one_cloud_funnel", - "description": "Collect logs from SentinelOne Cloud Funnel with Elastic Agent.", - "data_streams": [ - { - "dataset": "threat_intelligence_indicators", - "index_pattern": "logs-sentinel_one_cloud_funnel.threat_intelligence_indicators-*", - "title": "SentinelOne Cloud Funnel Threat Intelligence Indicator Events" - }, - { - "dataset": "scheduled_task", - "index_pattern": "logs-sentinel_one_cloud_funnel.scheduled_task-*", - "title": "SentinelOne Cloud Funnel Scheduled Task Events" - }, - { - "dataset": "cross_process", - "index_pattern": "logs-sentinel_one_cloud_funnel.cross_process-*", - "title": "SentinelOne Cloud Funnel cross_process Events" - }, - { - "dataset": "url", - "index_pattern": "logs-sentinel_one_cloud_funnel.url-*", - "title": "SentinelOne Cloud Funnel URL Events" - }, - { - "dataset": "file", - "index_pattern": "logs-sentinel_one_cloud_funnel.file-*", - "title": "SentinelOne Cloud Funnel File Events" - }, - { - "dataset": "module", - "index_pattern": "logs-sentinel_one_cloud_funnel.module-*", - "title": "SentinelOne Cloud Funnel Module Events" - }, - { - "dataset": "process", - "index_pattern": "logs-sentinel_one_cloud_funnel.process-*", - "title": "SentinelOne Cloud Funnel Process Events" - }, - { - "dataset": "dns", - "index_pattern": "logs-sentinel_one_cloud_funnel.dns-*", - "title": "SentinelOne Cloud Funnel dns Events" - }, - { - "dataset": "logins", - "index_pattern": "logs-sentinel_one_cloud_funnel.logins-*", - "title": "SentinelOne Cloud Funnel Logins Events" - }, - { - "dataset": "command_script", - "index_pattern": "logs-sentinel_one_cloud_funnel.command_script-*", - "title": "SentinelOne Cloud Funnel command_script Events" - }, - { - "dataset": "indicators", - "index_pattern": "logs-sentinel_one_cloud_funnel.indicators-*", - "title": "SentinelOne Cloud Funnel Indicator Events" - }, - { - "dataset": "event", - "index_pattern": "logs-sentinel_one_cloud_funnel.event-*", - "title": "Collect Event logs from SentinelOne Cloud Funnel." - }, - { - "dataset": "ip", - "index_pattern": "logs-sentinel_one_cloud_funnel.ip-*", - "title": "SentinelOne Cloud Funnel IP Events" - }, - { - "dataset": "registry", - "index_pattern": "logs-sentinel_one_cloud_funnel.registry-*", - "title": "SentinelOne Cloud Funnel Registry Events" - } - ], - "elser_embedding": "SentinelOne Cloud Funnel - Collect logs from SentinelOne Cloud Funnel with Elastic Agent. - SentinelOne Cloud Funnel Threat Intelligence Indicator Events SentinelOne Cloud Funnel Scheduled Task Events SentinelOne Cloud Funnel cross_process Events SentinelOne Cloud Funnel URL Events SentinelOne Cloud Funnel File Events SentinelOne Cloud Funnel Module Events SentinelOne Cloud Funnel Process Events SentinelOne Cloud Funnel dns Events SentinelOne Cloud Funnel Logins Events SentinelOne Cloud Funnel command_script Events SentinelOne Cloud Funnel Indicator Events Collect Event logs from SentinelOne Cloud Funnel. SentinelOne Cloud Funnel IP Events SentinelOne Cloud Funnel Registry Events" - }, - { - "title": "Cisco Meraki", - "id": "cisco_meraki", - "description": "Collect logs from Cisco Meraki with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-cisco_meraki.log-*", - "title": "Cisco Meraki logs (via Syslog)" - }, - { - "dataset": "events", - "index_pattern": "logs-cisco_meraki.events-*", - "title": "Cisco Meraki webhook events" - } - ], - "elser_embedding": "Cisco Meraki - Collect logs from Cisco Meraki with Elastic Agent. - Cisco Meraki logs (via Syslog) Cisco Meraki webhook events" - }, - { - "title": "Osquery Manager", - "id": "osquery_manager", - "description": "Deploy Osquery with Elastic Agent, then run and schedule queries in Kibana", - "data_streams": [ - { - "dataset": "result", - "index_pattern": "logs-osquery_manager.result-*", - "title": "Osquery Manager queries" - }, - { - "dataset": "action_responses", - "index_pattern": "logs-osquery_manager.action_responses-*", - "title": "Osquery Manager queries" - } - ], - "elser_embedding": "Osquery Manager - Deploy Osquery with Elastic Agent, then run and schedule queries in Kibana - Osquery Manager queries Osquery Manager queries" - }, - { - "title": "ModSecurity Audit", - "id": "modsecurity", - "description": "Collect logs from ModSecurity with Elastic Agent", - "data_streams": [ - { - "dataset": "auditlog", - "index_pattern": "logs-modsecurity.auditlog-*", - "title": "Modsecurity Audit Log" - } - ], - "elser_embedding": "ModSecurity Audit - Collect logs from ModSecurity with Elastic Agent - Modsecurity Audit Log" - }, - { - "title": "pfSense", - "id": "pfsense", - "description": "Collect logs from pfSense and OPNsense with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-pfsense.log-*", - "title": "pfSense log logs" - } - ], - "elser_embedding": "pfSense - Collect logs from pfSense and OPNsense with Elastic Agent. - pfSense log logs" - }, - { - "title": "Ceph", - "id": "ceph", - "description": "This Elastic integration collects metrics from Ceph instance.", - "data_streams": [ - { - "dataset": "cluster_disk", - "index_pattern": "logs-ceph.cluster_disk-*", - "title": "Cluster Disk metrics" - }, - { - "dataset": "osd_pool_stats", - "index_pattern": "logs-ceph.osd_pool_stats-*", - "title": "OSD Pool Stats" - }, - { - "dataset": "cluster_status", - "index_pattern": "logs-ceph.cluster_status-*", - "title": "Cluster Status metrics" - }, - { - "dataset": "pool_disk", - "index_pattern": "logs-ceph.pool_disk-*", - "title": "Pool Disk metrics" - }, - { - "dataset": "osd_tree", - "index_pattern": "logs-ceph.osd_tree-*", - "title": "OSD Tree metrics" - }, - { - "dataset": "osd_performance", - "index_pattern": "logs-ceph.osd_performance-*", - "title": "OSD Performance metrics" - }, - { - "dataset": "cluster_health", - "index_pattern": "logs-ceph.cluster_health-*", - "title": "Cluster Health metrics" - } - ], - "elser_embedding": "Ceph - This Elastic integration collects metrics from Ceph instance. - Cluster Disk metrics OSD Pool Stats Cluster Status metrics Pool Disk metrics OSD Tree metrics OSD Performance metrics Cluster Health metrics" - }, - { - "title": "Maltiverse", - "id": "ti_maltiverse", - "description": "Ingest threat intelligence indicators from Maltiverse feeds with Elastic Agent", - "data_streams": [ - { - "dataset": "indicator", - "index_pattern": "logs-ti_maltiverse.indicator-*", - "title": "Maltiverse indicator" - } - ], - "elser_embedding": "Maltiverse - Ingest threat intelligence indicators from Maltiverse feeds with Elastic Agent - Maltiverse indicator" - }, - { - "title": "Imperva", - "id": "imperva", - "description": "Collect logs from Imperva devices with Elastic Agent.", - "data_streams": [ - { - "dataset": "securesphere", - "index_pattern": "logs-imperva.securesphere-*", - "title": "Collect logs from Imperva SecureSphere" - } - ], - "elser_embedding": "Imperva - Collect logs from Imperva devices with Elastic Agent. - Collect logs from Imperva SecureSphere" - }, - { - "title": "Linux Metrics", - "id": "linux", - "description": "Collect metrics from Linux servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "memory", - "index_pattern": "logs-linux.memory-*", - "title": "Linux-only memory metrics" - }, - { - "dataset": "socket", - "index_pattern": "logs-linux.socket-*", - "title": "System socket metrics" - }, - { - "dataset": "ksm", - "index_pattern": "logs-linux.ksm-*", - "title": "Kernel Samepage merging metrics" - }, - { - "dataset": "raid", - "index_pattern": "logs-linux.raid-*", - "title": "System raid metrics" - }, - { - "dataset": "conntrack", - "index_pattern": "logs-linux.conntrack-*", - "title": "System conntrack metrics" - }, - { - "dataset": "network_summary", - "index_pattern": "logs-linux.network_summary-*", - "title": "System network_summary metrics" - }, - { - "dataset": "users", - "index_pattern": "logs-linux.users-*", - "title": "System users metrics" - }, - { - "dataset": "service", - "index_pattern": "logs-linux.service-*", - "title": "System service metrics" - }, - { - "dataset": "pageinfo", - "index_pattern": "logs-linux.pageinfo-*", - "title": "System page info metrics" - }, - { - "dataset": "iostat", - "index_pattern": "logs-linux.iostat-*", - "title": "Linux disk iostat metrics" - }, - { - "dataset": "entropy", - "index_pattern": "logs-linux.entropy-*", - "title": "System entropy metrics" - } - ], - "elser_embedding": "Linux Metrics - Collect metrics from Linux servers with Elastic Agent. - Linux-only memory metrics System socket metrics Kernel Samepage merging metrics System raid metrics System conntrack metrics System network_summary metrics System users metrics System service metrics System page info metrics Linux disk iostat metrics System entropy metrics" - }, - { - "title": "Cybereason", - "id": "cybereason", - "description": "Collect logs from Cybereason with Elastic Agent.", - "data_streams": [ - { - "dataset": "logon_session", - "index_pattern": "logs-cybereason.logon_session-*", - "title": "Collect Logon Session logs from Cybereason." - }, - { - "dataset": "poll_malop", - "index_pattern": "logs-cybereason.poll_malop-*", - "title": "Collect Poll Malop logs from Cybereason." - }, - { - "dataset": "suspicions_process", - "index_pattern": "logs-cybereason.suspicions_process-*", - "title": "Collect Suspicions Process logs from Cybereason." - }, - { - "dataset": "malop_process", - "index_pattern": "logs-cybereason.malop_process-*", - "title": "Collect Malop Process logs from Cybereason." - }, - { - "dataset": "malop_connection", - "index_pattern": "logs-cybereason.malop_connection-*", - "title": "Collect Malop Connection logs from Cybereason." - }, - { - "dataset": "malware", - "index_pattern": "logs-cybereason.malware-*", - "title": "Collect Malware logs from Cybereason." - } - ], - "elser_embedding": "Cybereason - Collect logs from Cybereason with Elastic Agent. - Collect Logon Session logs from Cybereason. Collect Poll Malop logs from Cybereason. Collect Suspicions Process logs from Cybereason. Collect Malop Process logs from Cybereason. Collect Malop Connection logs from Cybereason. Collect Malware logs from Cybereason." - }, - { - "title": "Kafka", - "id": "kafka", - "description": "Collect logs and metrics from Kafka servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "broker", - "index_pattern": "logs-kafka.broker-*", - "title": "Kafka broker metrics" - }, - { - "dataset": "consumergroup", - "index_pattern": "logs-kafka.consumergroup-*", - "title": "Kafka consumergroup metrics" - }, - { - "dataset": "partition", - "index_pattern": "logs-kafka.partition-*", - "title": "Kafka partition metrics" - }, - { - "dataset": "log", - "index_pattern": "logs-kafka.log-*", - "title": "Kafka log logs" - } - ], - "elser_embedding": "Kafka - Collect logs and metrics from Kafka servers with Elastic Agent. - Kafka broker metrics Kafka consumergroup metrics Kafka partition metrics Kafka log logs" - }, - { - "title": "Sophos Central", - "id": "sophos_central", - "description": "This Elastic integration collects logs from Sophos Central with Elastic Agent.", - "data_streams": [ - { - "dataset": "alert", - "index_pattern": "logs-sophos_central.alert-*", - "title": "Collect Sophos Central SIEM Alert logs" - }, - { - "dataset": "event", - "index_pattern": "logs-sophos_central.event-*", - "title": "Collect Sophos Central SIEM Events logs" - } - ], - "elser_embedding": "Sophos Central - This Elastic integration collects logs from Sophos Central with Elastic Agent. - Collect Sophos Central SIEM Alert logs Collect Sophos Central SIEM Events logs" - }, - { - "title": "PostgreSQL", - "id": "postgresql", - "description": "Collect logs and metrics from PostgreSQL servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "bgwriter", - "index_pattern": "logs-postgresql.bgwriter-*", - "title": "PostgreSQL bgwriter metrics" - }, - { - "dataset": "database", - "index_pattern": "logs-postgresql.database-*", - "title": "PostgreSQL database metrics" - }, - { - "dataset": "log", - "index_pattern": "logs-postgresql.log-*", - "title": "PostgreSQL logs" - }, - { - "dataset": "statement", - "index_pattern": "logs-postgresql.statement-*", - "title": "PostgreSQL statement metrics" - }, - { - "dataset": "activity", - "index_pattern": "logs-postgresql.activity-*", - "title": "PostgreSQL activity metrics" - } - ], - "elser_embedding": "PostgreSQL - Collect logs and metrics from PostgreSQL servers with Elastic Agent. - PostgreSQL bgwriter metrics PostgreSQL database metrics PostgreSQL logs PostgreSQL statement metrics PostgreSQL activity metrics" - }, - { - "title": "Corelight", - "id": "corelight", - "description": "Collect logs from Corelight with Elastic Agent.", - "data_streams": [], - "elser_embedding": "Corelight - Collect logs from Corelight with Elastic Agent. - " - }, - { - "title": "Threat Intelligence Utilities", - "id": "ti_util", - "description": "Prebuilt Threat Intelligence dashboard for Elastic Security", - "data_streams": [], - "elser_embedding": "Threat Intelligence Utilities - Prebuilt Threat Intelligence dashboard for Elastic Security - " - }, - { - "title": "Imperva Cloud WAF", - "id": "imperva_cloud_waf", - "description": "Collect logs from Imperva Cloud WAF with Elastic Agent.", - "data_streams": [ - { - "dataset": "event", - "index_pattern": "logs-imperva_cloud_waf.event-*", - "title": "Collect Imperva Cloud WAF Events" - } - ], - "elser_embedding": "Imperva Cloud WAF - Collect logs from Imperva Cloud WAF with Elastic Agent. - Collect Imperva Cloud WAF Events" - }, - { - "title": "File Integrity Monitoring", - "id": "fim", - "description": "The File Integrity Monitoring integration reports filesystem changes in real time.", - "data_streams": [ - { - "dataset": "event", - "index_pattern": "logs-fim.event-*", - "title": "Filesystem events" - } - ], - "elser_embedding": "File Integrity Monitoring - The File Integrity Monitoring integration reports filesystem changes in real time. - Filesystem events" - }, - { - "title": "Custom Websocket logs", - "id": "websocket", - "description": "Collect custom events from a socket server with Elastic agent.", - "data_streams": [], - "elser_embedding": "Custom Websocket logs - Collect custom events from a socket server with Elastic agent. - " - }, - { - "title": "SpyCloud Enterprise Protection", - "id": "spycloud", - "description": "Collect data from SpyCloud Enterprise Protection with Elastic Agent.", - "data_streams": [ - { - "dataset": "compass", - "index_pattern": "logs-spycloud.compass-*", - "title": "Collect Compass logs from SpyCloud Enterprise Protection." - }, - { - "dataset": "breach_record", - "index_pattern": "logs-spycloud.breach_record-*", - "title": "Collect Breach Record logs from SpyCloud Enterprise Protection." - }, - { - "dataset": "breach_catalog", - "index_pattern": "logs-spycloud.breach_catalog-*", - "title": "Collect Breach Catalog logs from SpyCloud Enterprise Protection." - } - ], - "elser_embedding": "SpyCloud Enterprise Protection - Collect data from SpyCloud Enterprise Protection with Elastic Agent. - Collect Compass logs from SpyCloud Enterprise Protection. Collect Breach Record logs from SpyCloud Enterprise Protection. Collect Breach Catalog logs from SpyCloud Enterprise Protection." - }, - { - "title": "Canva", - "id": "canva", - "description": "Collect logs from Canva with Elastic Agent.", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-canva.audit-*", - "title": "Collect Audit Logs from Canva" - } - ], - "elser_embedding": "Canva - Collect logs from Canva with Elastic Agent. - Collect Audit Logs from Canva" - }, - { - "title": "Microsoft Office 365", - "id": "o365", - "description": "Collect logs from Microsoft Office 365 with Elastic Agent.", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-o365.audit-*", - "title": "Microsoft Office 365 audit logs" - } - ], - "elser_embedding": "Microsoft Office 365 - Collect logs from Microsoft Office 365 with Elastic Agent. - Microsoft Office 365 audit logs" - }, - { - "title": "AWS", - "id": "aws", - "description": "Collect logs and metrics from Amazon Web Services (AWS) with Elastic Agent.", - "data_streams": [ - { - "dataset": "ec2_metrics", - "index_pattern": "logs-aws.ec2_metrics-*", - "title": "AWS EC2 metrics" - }, - { - "dataset": "apigateway_metrics", - "index_pattern": "logs-aws.apigateway_metrics-*", - "title": "AWS API Gateway metrics" - }, - { - "dataset": "ec2_logs", - "index_pattern": "logs-aws.ec2_logs-*", - "title": "AWS EC2 logs" - }, - { - "dataset": "cloudwatch_logs", - "index_pattern": "logs-aws.cloudwatch_logs-*", - "title": "AWS CloudWatch logs" - }, - { - "dataset": "billing", - "index_pattern": "logs-aws.billing-*", - "title": "AWS Billing Metrics" - }, - { - "dataset": "ebs", - "index_pattern": "logs-aws.ebs-*", - "title": "AWS EBS metrics" - }, - { - "dataset": "awshealth", - "index_pattern": "logs-aws.awshealth-*", - "title": "AWS Health" - }, - { - "dataset": "transitgateway", - "index_pattern": "logs-aws.transitgateway-*", - "title": "AWS Transit Gateway metrics" - }, - { - "dataset": "cloudtrail", - "index_pattern": "logs-aws.cloudtrail-*", - "title": "AWS CloudTrail Logs" - }, - { - "dataset": "vpn", - "index_pattern": "logs-aws.vpn-*", - "title": "AWS VPN metrics" - }, - { - "dataset": "sns", - "index_pattern": "logs-aws.sns-*", - "title": "AWS SNS metrics" - }, - { - "dataset": "firewall_metrics", - "index_pattern": "logs-aws.firewall_metrics-*", - "title": "AWS Network Firewall metrics" - }, - { - "dataset": "waf", - "index_pattern": "logs-aws.waf-*", - "title": "AWS WAF logs" - }, - { - "dataset": "emr_metrics", - "index_pattern": "logs-aws.emr_metrics-*", - "title": "AWS EMR metrics" - }, - { - "dataset": "firewall_logs", - "index_pattern": "logs-aws.firewall_logs-*", - "title": "AWS Network Firewall logs" - }, - { - "dataset": "lambda", - "index_pattern": "logs-aws.lambda-*", - "title": "AWS Lambda metrics" - }, - { - "dataset": "securityhub_insights", - "index_pattern": "logs-aws.securityhub_insights-*", - "title": "Collect AWS Security Hub Insights logs from AWS" - }, - { - "dataset": "redshift", - "index_pattern": "logs-aws.redshift-*", - "title": "Amazon Redshift metrics" - }, - { - "dataset": "inspector", - "index_pattern": "logs-aws.inspector-*", - "title": "Collect AWS Inspector logs from AWS" - }, - { - "dataset": "route53_resolver_logs", - "index_pattern": "logs-aws.route53_resolver_logs-*", - "title": "AWS Route 53 Resolver Query Logs" - }, - { - "dataset": "emr_logs", - "index_pattern": "logs-aws.emr_logs-*", - "title": "AWS EMR logs" - }, - { - "dataset": "elb_metrics", - "index_pattern": "logs-aws.elb_metrics-*", - "title": "AWS ELB metrics" - }, - { - "dataset": "s3access", - "index_pattern": "logs-aws.s3access-*", - "title": "AWS s3access logs" - }, - { - "dataset": "securityhub_findings", - "index_pattern": "logs-aws.securityhub_findings-*", - "title": "Collect AWS Security Hub Findings logs from AWS" - }, - { - "dataset": "vpcflow", - "index_pattern": "logs-aws.vpcflow-*", - "title": "AWS vpcflow logs" - }, - { - "dataset": "elb_logs", - "index_pattern": "logs-aws.elb_logs-*", - "title": "AWS ELB logs" - }, - { - "dataset": "kafka_metrics", - "index_pattern": "logs-aws.kafka_metrics-*", - "title": "AWS Kafka metrics" - }, - { - "dataset": "kinesis", - "index_pattern": "logs-aws.kinesis-*", - "title": "AWS Kinesis Data Stream metrics" - }, - { - "dataset": "cloudwatch_metrics", - "index_pattern": "logs-aws.cloudwatch_metrics-*", - "title": "AWS CloudWatch metrics" - }, - { - "dataset": "s3_daily_storage", - "index_pattern": "logs-aws.s3_daily_storage-*", - "title": "AWS S3 daily storage metrics" - }, - { - "dataset": "guardduty", - "index_pattern": "logs-aws.guardduty-*", - "title": "Collect Amazon GuardDuty Findings logs from AWS" - }, - { - "dataset": "rds", - "index_pattern": "logs-aws.rds-*", - "title": "AWS RDS metrics" - }, - { - "dataset": "ecs_metrics", - "index_pattern": "logs-aws.ecs_metrics-*", - "title": "AWS ECS metrics" - }, - { - "dataset": "s3_storage_lens", - "index_pattern": "logs-aws.s3_storage_lens-*", - "title": "AWS S3 Storage Lens metrics" - }, - { - "dataset": "route53_public_logs", - "index_pattern": "logs-aws.route53_public_logs-*", - "title": "AWS Route 53 Public Zone Logs" - }, - { - "dataset": "cloudfront_logs", - "index_pattern": "logs-aws.cloudfront_logs-*", - "title": "AWS CloudFront logs" - }, - { - "dataset": "usage", - "index_pattern": "logs-aws.usage-*", - "title": "AWS usage metrics" - }, - { - "dataset": "dynamodb", - "index_pattern": "logs-aws.dynamodb-*", - "title": "AWS DynamoDB metrics" - }, - { - "dataset": "apigateway_logs", - "index_pattern": "logs-aws.apigateway_logs-*", - "title": "AWS API Gateway logs" - }, - { - "dataset": "s3_request", - "index_pattern": "logs-aws.s3_request-*", - "title": "AWS S3 request metrics" - }, - { - "dataset": "sqs", - "index_pattern": "logs-aws.sqs-*", - "title": "AWS SQS metrics" - }, - { - "dataset": "natgateway", - "index_pattern": "logs-aws.natgateway-*", - "title": "AWS NAT gateway metrics" - } - ], - "elser_embedding": "AWS - Collect logs and metrics from Amazon Web Services (AWS) with Elastic Agent. - AWS EC2 metrics AWS API Gateway metrics AWS EC2 logs AWS CloudWatch logs AWS Billing Metrics AWS EBS metrics AWS Health AWS Transit Gateway metrics AWS CloudTrail Logs AWS VPN metrics AWS SNS metrics AWS Network Firewall metrics AWS WAF logs AWS EMR metrics AWS Network Firewall logs AWS Lambda metrics Collect AWS Security Hub Insights logs from AWS Amazon Redshift metrics Collect AWS Inspector logs from AWS AWS Route 53 Resolver Query Logs AWS EMR logs AWS ELB metrics AWS s3access logs Collect AWS Security Hub Findings logs from AWS AWS vpcflow logs AWS ELB logs AWS Kafka metrics AWS Kinesis Data Stream metrics AWS CloudWatch metrics AWS S3 daily storage metrics Collect Amazon GuardDuty Findings logs from AWS AWS RDS metrics AWS ECS metrics AWS S3 Storage Lens metrics AWS Route 53 Public Zone Logs AWS CloudFront logs AWS usage metrics AWS DynamoDB metrics AWS API Gateway logs AWS S3 request metrics AWS SQS metrics AWS NAT gateway metrics" - }, - { - "title": "Nginx Ingress Controller Logs", - "id": "nginx_ingress_controller", - "description": "Collect Nginx Ingress Controller logs.", - "data_streams": [ - { - "dataset": "access", - "index_pattern": "logs-nginx_ingress_controller.access-*", - "title": "Nginx Ingress Controller access logs" - }, - { - "dataset": "error", - "index_pattern": "logs-nginx_ingress_controller.error-*", - "title": "Nginx Ingress Controller error logs" - } - ], - "elser_embedding": "Nginx Ingress Controller Logs - Collect Nginx Ingress Controller logs. - Nginx Ingress Controller access logs Nginx Ingress Controller error logs" - }, - { - "title": "Cisco Umbrella", - "id": "cisco_umbrella", - "description": "Collect logs from Cisco Umbrella with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-cisco_umbrella.log-*", - "title": "Cisco Umbrella logs" - } - ], - "elser_embedding": "Cisco Umbrella - Collect logs from Cisco Umbrella with Elastic Agent. - Cisco Umbrella logs" - }, - { - "title": "Cloudflare Logpush", - "id": "cloudflare_logpush", - "description": "Collect and parse logs from Cloudflare API with Elastic Agent.", - "data_streams": [ - { - "dataset": "http_request", - "index_pattern": "logs-cloudflare_logpush.http_request-*", - "title": "Collect HTTP Request logs from Cloudflare" - }, - { - "dataset": "access_request", - "index_pattern": "logs-cloudflare_logpush.access_request-*", - "title": "Collect Access Request logs from Cloudflare" - }, - { - "dataset": "network_session", - "index_pattern": "logs-cloudflare_logpush.network_session-*", - "title": "Collect Zero Trust Network Session logs from Cloudflare" - }, - { - "dataset": "spectrum_event", - "index_pattern": "logs-cloudflare_logpush.spectrum_event-*", - "title": "Collect Spectrum Event logs from Cloudflare" - }, - { - "dataset": "gateway_http", - "index_pattern": "logs-cloudflare_logpush.gateway_http-*", - "title": "Collect Gateway HTTP logs from Cloudflare" - }, - { - "dataset": "casb", - "index_pattern": "logs-cloudflare_logpush.casb-*", - "title": "Collect CASB Findings logs from Cloudflare" - }, - { - "dataset": "magic_ids", - "index_pattern": "logs-cloudflare_logpush.magic_ids-*", - "title": "Collect Magic IDS logs from Cloudflare" - }, - { - "dataset": "workers_trace", - "index_pattern": "logs-cloudflare_logpush.workers_trace-*", - "title": "Collect Workers Trace Event logs from Cloudflare" - }, - { - "dataset": "audit", - "index_pattern": "logs-cloudflare_logpush.audit-*", - "title": "Collect Audit logs from Cloudflare" - }, - { - "dataset": "nel_report", - "index_pattern": "logs-cloudflare_logpush.nel_report-*", - "title": "Collect NEL Report logs from Cloudflare" - }, - { - "dataset": "network_analytics", - "index_pattern": "logs-cloudflare_logpush.network_analytics-*", - "title": "Collect Network Analytics logs from Cloudflare" - }, - { - "dataset": "dns", - "index_pattern": "logs-cloudflare_logpush.dns-*", - "title": "Collect DNS logs from Cloudflare" - }, - { - "dataset": "device_posture", - "index_pattern": "logs-cloudflare_logpush.device_posture-*", - "title": "Collect Device Posture Results logs from Cloudflare" - }, - { - "dataset": "gateway_dns", - "index_pattern": "logs-cloudflare_logpush.gateway_dns-*", - "title": "Collect Gateway DNS logs from Cloudflare" - }, - { - "dataset": "dns_firewall", - "index_pattern": "logs-cloudflare_logpush.dns_firewall-*", - "title": "Collect DNS Firewall logs from Cloudflare" - }, - { - "dataset": "sinkhole_http", - "index_pattern": "logs-cloudflare_logpush.sinkhole_http-*", - "title": "Collect Sinkhole HTTP logs from Cloudflare" - }, - { - "dataset": "firewall_event", - "index_pattern": "logs-cloudflare_logpush.firewall_event-*", - "title": "Collect Firewall Event logs from Cloudflare" - }, - { - "dataset": "gateway_network", - "index_pattern": "logs-cloudflare_logpush.gateway_network-*", - "title": "Collect Gateway Network logs from Cloudflare" - } - ], - "elser_embedding": "Cloudflare Logpush - Collect and parse logs from Cloudflare API with Elastic Agent. - Collect HTTP Request logs from Cloudflare Collect Access Request logs from Cloudflare Collect Zero Trust Network Session logs from Cloudflare Collect Spectrum Event logs from Cloudflare Collect Gateway HTTP logs from Cloudflare Collect CASB Findings logs from Cloudflare Collect Magic IDS logs from Cloudflare Collect Workers Trace Event logs from Cloudflare Collect Audit logs from Cloudflare Collect NEL Report logs from Cloudflare Collect Network Analytics logs from Cloudflare Collect DNS logs from Cloudflare Collect Device Posture Results logs from Cloudflare Collect Gateway DNS logs from Cloudflare Collect DNS Firewall logs from Cloudflare Collect Sinkhole HTTP logs from Cloudflare Collect Firewall Event logs from Cloudflare Collect Gateway Network logs from Cloudflare" - }, - { - "title": "Microsoft DHCP", - "id": "microsoft_dhcp", - "description": "Collect logs from Microsoft DHCP with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-microsoft_dhcp.log-*", - "title": "Microsoft DHCP Logs" - } - ], - "elser_embedding": "Microsoft DHCP - Collect logs from Microsoft DHCP with Elastic Agent. - Microsoft DHCP Logs" - }, - { - "title": "Netskope", - "id": "netskope", - "description": "Collect logs from Netskope with Elastic Agent.", - "data_streams": [ - { - "dataset": "alerts", - "index_pattern": "logs-netskope.alerts-*", - "title": "Alerts" - }, - { - "dataset": "events", - "index_pattern": "logs-netskope.events-*", - "title": "Events" - } - ], - "elser_embedding": "Netskope - Collect logs from Netskope with Elastic Agent. - Alerts Events" - }, - { - "title": "Suricata", - "id": "suricata", - "description": "Collect logs from Suricata with Elastic Agent.", - "data_streams": [ - { - "dataset": "eve", - "index_pattern": "logs-suricata.eve-*", - "title": "Suricata eve logs" - } - ], - "elser_embedding": "Suricata - Collect logs from Suricata with Elastic Agent. - Suricata eve logs" - }, - { - "title": "Custom Azure Logs", - "id": "azure_logs", - "description": "Collect log events from Azure Event Hubs with Elastic Agent", - "data_streams": [], - "elser_embedding": "Custom Azure Logs - Collect log events from Azure Event Hubs with Elastic Agent - " - }, - { - "title": "Zscaler Private Access", - "id": "zscaler_zpa", - "description": "Collect logs from Zscaler Private Access (ZPA) with Elastic Agent.", - "data_streams": [ - { - "dataset": "browser_access", - "index_pattern": "logs-zscaler_zpa.browser_access-*", - "title": "Browser Access Logs" - }, - { - "dataset": "app_connector_status", - "index_pattern": "logs-zscaler_zpa.app_connector_status-*", - "title": "App Connector Status Logs" - }, - { - "dataset": "user_status", - "index_pattern": "logs-zscaler_zpa.user_status-*", - "title": "User Status Logs" - }, - { - "dataset": "audit", - "index_pattern": "logs-zscaler_zpa.audit-*", - "title": "Audit Logs" - }, - { - "dataset": "user_activity", - "index_pattern": "logs-zscaler_zpa.user_activity-*", - "title": "User Activity Logs" - } - ], - "elser_embedding": "Zscaler Private Access - Collect logs from Zscaler Private Access (ZPA) with Elastic Agent. - Browser Access Logs App Connector Status Logs User Status Logs Audit Logs User Activity Logs" - }, - { - "title": "Cisco Aironet", - "id": "cisco_aironet", - "description": "Integration for Cisco Aironet WLC Logs", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-cisco_aironet.log-*", - "title": "Cisco Aironet logs" - } - ], - "elser_embedding": "Cisco Aironet - Integration for Cisco Aironet WLC Logs - Cisco Aironet logs" - }, - { - "title": "Collective Intelligence Framework v3", - "id": "ti_cif3", - "description": "Ingest threat indicators from a Collective Intelligence Framework v3 instance with Elastic Agent.", - "data_streams": [ - { - "dataset": "feed", - "index_pattern": "logs-ti_cif3.feed-*", - "title": "CIFv3 Feed" - } - ], - "elser_embedding": "Collective Intelligence Framework v3 - Ingest threat indicators from a Collective Intelligence Framework v3 instance with Elastic Agent. - CIFv3 Feed" - }, - { - "title": "Bitwarden", - "id": "bitwarden", - "description": "Collect logs from Bitwarden with Elastic Agent.", - "data_streams": [ - { - "dataset": "group", - "index_pattern": "logs-bitwarden.group-*", - "title": "Collect Group logs from Bitwarden" - }, - { - "dataset": "policy", - "index_pattern": "logs-bitwarden.policy-*", - "title": "Collect Policy logs from Bitwarden" - }, - { - "dataset": "member", - "index_pattern": "logs-bitwarden.member-*", - "title": "Collect Member logs from Bitwarden" - }, - { - "dataset": "event", - "index_pattern": "logs-bitwarden.event-*", - "title": "Collect Event logs from Bitwarden" - }, - { - "dataset": "collection", - "index_pattern": "logs-bitwarden.collection-*", - "title": "Collect Collection logs from Bitwarden" - } - ], - "elser_embedding": "Bitwarden - Collect logs from Bitwarden with Elastic Agent. - Collect Group logs from Bitwarden Collect Policy logs from Bitwarden Collect Member logs from Bitwarden Collect Event logs from Bitwarden Collect Collection logs from Bitwarden" - }, - { - "title": "Kibana", - "id": "kibana", - "description": "Collect logs and metrics from Kibana with Elastic Agent.", - "data_streams": [ - { - "dataset": "node_actions", - "index_pattern": "logs-kibana.node_actions-*", - "title": "Kibana node_actions metrics" - }, - { - "dataset": "stats", - "index_pattern": "logs-kibana.stats-*", - "title": "Kibana stats metrics" - }, - { - "dataset": "audit", - "index_pattern": "logs-kibana.audit-*", - "title": "kibana audit logs" - }, - { - "dataset": "task_manager_metrics", - "index_pattern": "logs-kibana.task_manager_metrics-*", - "title": "Kibana task manager metrics" - }, - { - "dataset": "cluster_rules", - "index_pattern": "logs-kibana.cluster_rules-*", - "title": "Kibana cluster_rules metrics" - }, - { - "dataset": "background_task_utilization", - "index_pattern": "logs-kibana.background_task_utilization-*", - "title": "Kibana background task utilization metrics" - }, - { - "dataset": "log", - "index_pattern": "logs-kibana.log-*", - "title": "Kibana logs" - }, - { - "dataset": "node_rules", - "index_pattern": "logs-kibana.node_rules-*", - "title": "Kibana node_rules metrics" - }, - { - "dataset": "status", - "index_pattern": "logs-kibana.status-*", - "title": "Kibana status metrics" - }, - { - "dataset": "cluster_actions", - "index_pattern": "logs-kibana.cluster_actions-*", - "title": "Kibana cluster_actions metrics" - } - ], - "elser_embedding": "Kibana - Collect logs and metrics from Kibana with Elastic Agent. - Kibana node_actions metrics Kibana stats metrics kibana audit logs Kibana task manager metrics Kibana cluster_rules metrics Kibana background task utilization metrics Kibana logs Kibana node_rules metrics Kibana status metrics Kibana cluster_actions metrics" - }, - { - "title": "Digital Guardian", - "id": "digital_guardian", - "description": "Collect logs from Digital Guardian with Elastic Agent.", - "data_streams": [ - { - "dataset": "arc", - "index_pattern": "logs-digital_guardian.arc-*", - "title": "Digital Guardian ARC Logs" - } - ], - "elser_embedding": "Digital Guardian - Collect logs from Digital Guardian with Elastic Agent. - Digital Guardian ARC Logs" - }, - { - "title": "MySQL", - "id": "mysql", - "description": "Collect logs and metrics from MySQL servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "performance", - "index_pattern": "logs-mysql.performance-*", - "title": "MySQL performance metrics" - }, - { - "dataset": "error", - "index_pattern": "logs-mysql.error-*", - "title": "MySQL error logs" - }, - { - "dataset": "slowlog", - "index_pattern": "logs-mysql.slowlog-*", - "title": "MySQL slowlog logs" - }, - { - "dataset": "galera_status", - "index_pattern": "logs-mysql.galera_status-*", - "title": "MySQL galera_status metrics" - }, - { - "dataset": "replica_status", - "index_pattern": "logs-mysql.replica_status-*", - "title": "Collect replica status metrics from mysql" - }, - { - "dataset": "status", - "index_pattern": "logs-mysql.status-*", - "title": "MySQL status metrics" - } - ], - "elser_embedding": "MySQL - Collect logs and metrics from MySQL servers with Elastic Agent. - MySQL performance metrics MySQL error logs MySQL slowlog logs MySQL galera_status metrics Collect replica status metrics from mysql MySQL status metrics" - }, - { - "title": "CISA Known Exploited Vulnerabilities", - "id": "cisa_kevs", - "description": "This package allows the ingest of known exploited vulnerabilities according to the Cybersecurity and Infrastructure Security Agency of the United States of America. This information could be used to enrich or track exisiting vulnerabilities that are known to be exploited in the wild.", - "data_streams": [ - { - "dataset": "vulnerability", - "index_pattern": "logs-cisa_kevs.vulnerability-*", - "title": "CISA Known Exploited Vulnerabilities List" - } - ], - "elser_embedding": "CISA Known Exploited Vulnerabilities - This package allows the ingest of known exploited vulnerabilities according to the Cybersecurity and Infrastructure Security Agency of the United States of America. This information could be used to enrich or track exisiting vulnerabilities that are known to be exploited in the wild. - CISA Known Exploited Vulnerabilities List" - }, - { - "title": "StormShield SNS", - "id": "stormshield", - "description": "Stormshield SNS integration.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-stormshield.log-*", - "title": "StormShield SNS logs" - } - ], - "elser_embedding": "StormShield SNS - Stormshield SNS integration. - StormShield SNS logs" - }, - { - "title": "1Password", - "id": "1password", - "description": "Collect logs from 1Password with Elastic Agent.", - "data_streams": [ - { - "dataset": "item_usages", - "index_pattern": "logs-1password.item_usages-*", - "title": "Collect 1Password item usages events" - }, - { - "dataset": "signin_attempts", - "index_pattern": "logs-1password.signin_attempts-*", - "title": "1Password sign-in attempt events" - }, - { - "dataset": "audit_events", - "index_pattern": "logs-1password.audit_events-*", - "title": "Collect 1Password audit events" - } - ], - "elser_embedding": "1Password - Collect logs from 1Password with Elastic Agent. - Collect 1Password item usages events 1Password sign-in attempt events Collect 1Password audit events" - }, - { - "title": "Azure Network Watcher NSG", - "id": "azure_network_watcher_nsg", - "description": "Collect logs from Azure Network Watcher NSG with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-azure_network_watcher_nsg.log-*", - "title": "Collect NSG logs from Azure Network Watcher" - } - ], - "elser_embedding": "Azure Network Watcher NSG - Collect logs from Azure Network Watcher NSG with Elastic Agent. - Collect NSG logs from Azure Network Watcher" - }, - { - "title": "WebSphere Application Server", - "id": "websphere_application_server", - "description": "Collects metrics from IBM WebSphere Application Server with Elastic Agent.", - "data_streams": [ - { - "dataset": "threadpool", - "index_pattern": "logs-websphere_application_server.threadpool-*", - "title": "ThreadPool metrics" - }, - { - "dataset": "servlet", - "index_pattern": "logs-websphere_application_server.servlet-*", - "title": "Servlet metrics" - }, - { - "dataset": "session_manager", - "index_pattern": "logs-websphere_application_server.session_manager-*", - "title": "Session Manager metrics" - }, - { - "dataset": "jdbc", - "index_pattern": "logs-websphere_application_server.jdbc-*", - "title": "JDBC metrics" - } - ], - "elser_embedding": "WebSphere Application Server - Collects metrics from IBM WebSphere Application Server with Elastic Agent. - ThreadPool metrics Servlet metrics Session Manager metrics JDBC metrics" - }, - { - "title": "GitLab", - "id": "gitlab", - "description": "Collect logs from GitLab with Elastic Agent.", - "data_streams": [ - { - "dataset": "sidekiq", - "index_pattern": "logs-gitlab.sidekiq-*", - "title": "GitLab Sidekiq logs" - }, - { - "dataset": "audit", - "index_pattern": "logs-gitlab.audit-*", - "title": "Audit" - }, - { - "dataset": "auth", - "index_pattern": "logs-gitlab.auth-*", - "title": "Auth" - }, - { - "dataset": "application", - "index_pattern": "logs-gitlab.application-*", - "title": "Application" - }, - { - "dataset": "pages", - "index_pattern": "logs-gitlab.pages-*", - "title": "GitLab Pages logs" - }, - { - "dataset": "production", - "index_pattern": "logs-gitlab.production-*", - "title": "GitLab Production logs" - }, - { - "dataset": "api", - "index_pattern": "logs-gitlab.api-*", - "title": "GitLab API logs" - } - ], - "elser_embedding": "GitLab - Collect logs from GitLab with Elastic Agent. - GitLab Sidekiq logs Audit Auth Application GitLab Pages logs GitLab Production logs GitLab API logs" - }, - { - "title": "Custom Logs", - "id": "log", - "description": "Collect custom logs with Elastic Agent.", - "data_streams": [], - "elser_embedding": "Custom Logs - Collect custom logs with Elastic Agent. - " - }, - { - "title": "Tenable Vulnerability Management", - "id": "tenable_io", - "description": "Collect logs from Tenable Vulnerability Management with Elastic Agent.", - "data_streams": [ - { - "dataset": "plugin", - "index_pattern": "logs-tenable_io.plugin-*", - "title": "Collect Plugin logs from Tenable Vulnerability Management" - }, - { - "dataset": "vulnerability", - "index_pattern": "logs-tenable_io.vulnerability-*", - "title": "Collect Vulnerability logs from Tenable Vulnerability Management" - }, - { - "dataset": "scan", - "index_pattern": "logs-tenable_io.scan-*", - "title": "Collect Scan logs from Tenable Vulnerability Management" - }, - { - "dataset": "asset", - "index_pattern": "logs-tenable_io.asset-*", - "title": "Collect Asset data from Tenable Vulnerability Management" - } - ], - "elser_embedding": "Tenable Vulnerability Management - Collect logs from Tenable Vulnerability Management with Elastic Agent. - Collect Plugin logs from Tenable Vulnerability Management Collect Vulnerability logs from Tenable Vulnerability Management Collect Scan logs from Tenable Vulnerability Management Collect Asset data from Tenable Vulnerability Management" - }, - { - "title": "Falco", - "id": "falco", - "description": "Collect events and alerts from Falco using Elastic Agent", - "data_streams": [ - { - "dataset": "alerts", - "index_pattern": "logs-falco.alerts-*", - "title": "Falco Alerts" - } - ], - "elser_embedding": "Falco - Collect events and alerts from Falco using Elastic Agent - Falco Alerts" - }, - { - "title": "Docker", - "id": "docker", - "description": "Collect metrics and logs from Docker instances with Elastic Agent.", - "data_streams": [ - { - "dataset": "memory", - "index_pattern": "logs-docker.memory-*", - "title": "Docker memory metrics" - }, - { - "dataset": "network", - "index_pattern": "logs-docker.network-*", - "title": "Docker network metrics" - }, - { - "dataset": "image", - "index_pattern": "logs-docker.image-*", - "title": "Docker image metrics" - }, - { - "dataset": "container", - "index_pattern": "logs-docker.container-*", - "title": "Docker container metrics" - }, - { - "dataset": "info", - "index_pattern": "logs-docker.info-*", - "title": "Docker info metrics" - }, - { - "dataset": "container_logs", - "index_pattern": "logs-docker.container_logs-*", - "title": "Docker container logs" - }, - { - "dataset": "diskio", - "index_pattern": "logs-docker.diskio-*", - "title": "Docker diskio metrics" - }, - { - "dataset": "event", - "index_pattern": "logs-docker.event-*", - "title": "Docker event metrics" - }, - { - "dataset": "healthcheck", - "index_pattern": "logs-docker.healthcheck-*", - "title": "Docker healthcheck metrics" - }, - { - "dataset": "cpu", - "index_pattern": "logs-docker.cpu-*", - "title": "Docker cpu metrics" - } - ], - "elser_embedding": "Docker - Collect metrics and logs from Docker instances with Elastic Agent. - Docker memory metrics Docker network metrics Docker image metrics Docker container metrics Docker info metrics Docker container logs Docker diskio metrics Docker event metrics Docker healthcheck metrics Docker cpu metrics" - }, - { - "title": "Elastic Synthetics Dashboards", - "id": "synthetics_dashboards", - "description": "Explore Elastic Synthetics metrics with these dashboards.", - "data_streams": [], - "elser_embedding": "Elastic Synthetics Dashboards - Explore Elastic Synthetics metrics with these dashboards. - " - }, - { - "title": "Azure Billing Metrics", - "id": "azure_billing", - "description": "Collect billing metrics with Elastic Agent.", - "data_streams": [ - { - "dataset": "billing", - "index_pattern": "logs-azure_billing.billing-*", - "title": "Azure Billing Metrics" - } - ], - "elser_embedding": "Azure Billing Metrics - Collect billing metrics with Elastic Agent. - Azure Billing Metrics" - }, - { - "title": "Couchbase", - "id": "couchbase", - "description": "Collect metrics from Couchbase databases with Elastic Agent.", - "data_streams": [ - { - "dataset": "cache", - "index_pattern": "logs-couchbase.cache-*", - "title": "Couchbase Sync Gateway Cache metrics." - }, - { - "dataset": "cbl_replication", - "index_pattern": "logs-couchbase.cbl_replication-*", - "title": "Couchbase Sync Gateway CBL Replications metrics" - }, - { - "dataset": "query_index", - "index_pattern": "logs-couchbase.query_index-*", - "title": "Query Index metrics" - }, - { - "dataset": "xdcr", - "index_pattern": "logs-couchbase.xdcr-*", - "title": "Couchbase XDCR Metrics" - }, - { - "dataset": "miscellaneous", - "index_pattern": "logs-couchbase.miscellaneous-*", - "title": "Couchbase Sync Gateway Delta Sync, Import, Security and GSI views metrics." - }, - { - "dataset": "node", - "index_pattern": "logs-couchbase.node-*", - "title": "Node metrics" - }, - { - "dataset": "resource", - "index_pattern": "logs-couchbase.resource-*", - "title": "Couchbase Sync Gateway Resource Utilization metrics." - }, - { - "dataset": "bucket", - "index_pattern": "logs-couchbase.bucket-*", - "title": "Couchbase bucket metrics" - }, - { - "dataset": "cluster", - "index_pattern": "logs-couchbase.cluster-*", - "title": "Couchbase cluster metrics" - }, - { - "dataset": "database_stats", - "index_pattern": "logs-couchbase.database_stats-*", - "title": "Couchbase Sync Gateway Database Stats metrics." - } - ], - "elser_embedding": "Couchbase - Collect metrics from Couchbase databases with Elastic Agent. - Couchbase Sync Gateway Cache metrics. Couchbase Sync Gateway CBL Replications metrics Query Index metrics Couchbase XDCR Metrics Couchbase Sync Gateway Delta Sync, Import, Security and GSI views metrics. Node metrics Couchbase Sync Gateway Resource Utilization metrics. Couchbase bucket metrics Couchbase cluster metrics Couchbase Sync Gateway Database Stats metrics." - }, - { - "title": "VMware Carbon Black Cloud", - "id": "carbon_black_cloud", - "description": "Collect logs from VMWare Carbon Black Cloud with Elastic Agent.", - "data_streams": [ - { - "dataset": "watchlist_hit", - "index_pattern": "logs-carbon_black_cloud.watchlist_hit-*", - "title": "Watchlist Hit" - }, - { - "dataset": "asset_vulnerability_summary", - "index_pattern": "logs-carbon_black_cloud.asset_vulnerability_summary-*", - "title": "Asset Vulnerability Summary" - }, - { - "dataset": "endpoint_event", - "index_pattern": "logs-carbon_black_cloud.endpoint_event-*", - "title": "Endpoint Event" - }, - { - "dataset": "audit", - "index_pattern": "logs-carbon_black_cloud.audit-*", - "title": "Audit" - }, - { - "dataset": "alert", - "index_pattern": "logs-carbon_black_cloud.alert-*", - "title": "Alert" - }, - { - "dataset": "alert_v7", - "index_pattern": "logs-carbon_black_cloud.alert_v7-*", - "title": "Alert V7" - } - ], - "elser_embedding": "VMware Carbon Black Cloud - Collect logs from VMWare Carbon Black Cloud with Elastic Agent. - Watchlist Hit Asset Vulnerability Summary Endpoint Event Audit Alert Alert V7" - }, - { - "title": "Universal Profiling Symbolizer", - "id": "profiler_symbolizer", - "description": "Fleet-wide, whole-system, continuous profiling with zero instrumentation.", - "data_streams": [], - "elser_embedding": "Universal Profiling Symbolizer - Fleet-wide, whole-system, continuous profiling with zero instrumentation. - " - }, - { - "title": "Fortinet FortiProxy", - "id": "fortinet_fortiproxy", - "description": "Collect logs from Fortinet FortiProxy with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-fortinet_fortiproxy.log-*", - "title": "Collect logs from Fortinet FortiProxy" - } - ], - "elser_embedding": "Fortinet FortiProxy - Collect logs from Fortinet FortiProxy with Elastic Agent. - Collect logs from Fortinet FortiProxy" - }, - { - "title": "MongoDB Atlas", - "id": "mongodb_atlas", - "description": "This Elastic integration collects logs and metrics from MongoDB Atlas instance.", - "data_streams": [ - { - "dataset": "mongod_database", - "index_pattern": "logs-mongodb_atlas.mongod_database-*", - "title": "Collect Mongod Database logs from MongoDB Atlas" - }, - { - "dataset": "disk", - "index_pattern": "logs-mongodb_atlas.disk-*", - "title": "Collect Disk metrics from MongoDB Atlas" - }, - { - "dataset": "project", - "index_pattern": "logs-mongodb_atlas.project-*", - "title": "Collect Project logs from MongoDB Atlas" - }, - { - "dataset": "process", - "index_pattern": "logs-mongodb_atlas.process-*", - "title": "Collect Process metrics from MongoDB Atlas" - }, - { - "dataset": "alert", - "index_pattern": "logs-mongodb_atlas.alert-*", - "title": "Collect Alert logs from MongoDB Atlas" - }, - { - "dataset": "mongod_audit", - "index_pattern": "logs-mongodb_atlas.mongod_audit-*", - "title": "Collect Mongod Audit logs from MongoDB Atlas" - }, - { - "dataset": "organization", - "index_pattern": "logs-mongodb_atlas.organization-*", - "title": "Collect Organization logs from MongoDB Atlas" - }, - { - "dataset": "hardware", - "index_pattern": "logs-mongodb_atlas.hardware-*", - "title": "Collect Hardware metrics from MongoDB Atlas" - } - ], - "elser_embedding": "MongoDB Atlas - This Elastic integration collects logs and metrics from MongoDB Atlas instance. - Collect Mongod Database logs from MongoDB Atlas Collect Disk metrics from MongoDB Atlas Collect Project logs from MongoDB Atlas Collect Process metrics from MongoDB Atlas Collect Alert logs from MongoDB Atlas Collect Mongod Audit logs from MongoDB Atlas Collect Organization logs from MongoDB Atlas Collect Hardware metrics from MongoDB Atlas" - }, - { - "title": "Zero Networks", - "id": "zeronetworks", - "description": "Zero Networks Logs integration", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-zeronetworks.audit-*", - "title": "Zero Networks Audit Logs" - } - ], - "elser_embedding": "Zero Networks - Zero Networks Logs integration - Zero Networks Audit Logs" - }, - { - "title": "CockroachDB Metrics", - "id": "cockroachdb", - "description": "Collect metrics from CockroachDB servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "status", - "index_pattern": "logs-cockroachdb.status-*", - "title": "Status" - } - ], - "elser_embedding": "CockroachDB Metrics - Collect metrics from CockroachDB servers with Elastic Agent. - Status" - }, - { - "title": "Microsoft Exchange Server", - "id": "microsoft_exchange_server", - "description": "Collect logs from Microsoft Exchange Server with Elastic Agent.", - "data_streams": [ - { - "dataset": "imap4_pop3", - "index_pattern": "logs-microsoft_exchange_server.imap4_pop3-*", - "title": "Exchange Server IMAP4 POP3" - }, - { - "dataset": "httpproxy", - "index_pattern": "logs-microsoft_exchange_server.httpproxy-*", - "title": "Exchange HTTPProxy" - }, - { - "dataset": "smtp", - "index_pattern": "logs-microsoft_exchange_server.smtp-*", - "title": "Exchange SMTP" - }, - { - "dataset": "messagetracking", - "index_pattern": "logs-microsoft_exchange_server.messagetracking-*", - "title": "Exchange Messagetracking" - } - ], - "elser_embedding": "Microsoft Exchange Server - Collect logs from Microsoft Exchange Server with Elastic Agent. - Exchange Server IMAP4 POP3 Exchange HTTPProxy Exchange SMTP Exchange Messagetracking" - }, - { - "title": "Cisco Secure Email Gateway", - "id": "cisco_secure_email_gateway", - "description": "Collect logs from Cisco Secure Email Gateway with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-cisco_secure_email_gateway.log-*", - "title": "Cisco Secure Email Gateway logs" - } - ], - "elser_embedding": "Cisco Secure Email Gateway - Collect logs from Cisco Secure Email Gateway with Elastic Agent. - Cisco Secure Email Gateway logs" - }, - { - "title": "Prometheus Input", - "id": "prometheus_input", - "description": "Collects metrics from Prometheus exporter.", - "data_streams": [], - "elser_embedding": "Prometheus Input - Collects metrics from Prometheus exporter. - " - }, - { - "title": "PingOne", - "id": "ping_one", - "description": "Collect logs from PingOne with Elastic-Agent.", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-ping_one.audit-*", - "title": "Collect Audit logs from PingOne" - } - ], - "elser_embedding": "PingOne - Collect logs from PingOne with Elastic-Agent. - Collect Audit logs from PingOne" - }, - { - "title": "Squid Proxy", - "id": "squid", - "description": "Collect and parse logs from Squid devices with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-squid.log-*", - "title": "Squid logs" - } - ], - "elser_embedding": "Squid Proxy - Collect and parse logs from Squid devices with Elastic Agent. - Squid logs" - }, - { - "title": "Zoom", - "id": "zoom", - "description": "Collect logs from Zoom with Elastic Agent.", - "data_streams": [ - { - "dataset": "webhook", - "index_pattern": "logs-zoom.webhook-*", - "title": "Zoom webhook logs" - } - ], - "elser_embedding": "Zoom - Collect logs from Zoom with Elastic Agent. - Zoom webhook logs" - }, - { - "title": "Auth0", - "id": "auth0", - "description": "Collect logs from Auth0 with Elastic Agent.", - "data_streams": [ - { - "dataset": "logs", - "index_pattern": "logs-auth0.logs-*", - "title": "Auth0 logs" - } - ], - "elser_embedding": "Auth0 - Collect logs from Auth0 with Elastic Agent. - Auth0 logs" - }, - { - "title": "Tomcat NetWitness Logs", - "id": "tomcat", - "description": "Collect and parse logs from Apache Tomcat servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-tomcat.log-*", - "title": "Apache Tomcat logs" - } - ], - "elser_embedding": "Tomcat NetWitness Logs - Collect and parse logs from Apache Tomcat servers with Elastic Agent. - Apache Tomcat logs" - }, - { - "title": "Auditd Logs", - "id": "auditd", - "description": "Collect logs from Linux audit daemon with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-auditd.log-*", - "title": "Auditd logs" - } - ], - "elser_embedding": "Auditd Logs - Collect logs from Linux audit daemon with Elastic Agent. - Auditd logs" - }, - { - "title": "SQL Input", - "id": "sql", - "description": "Collects Metrics by Quering on SQL Databases", - "data_streams": [], - "elser_embedding": "SQL Input - Collects Metrics by Quering on SQL Databases - " - }, - { - "title": "Azure Frontdoor", - "id": "azure_frontdoor", - "description": "This Elastic integration collects logs from Azure Frontdoor.", - "data_streams": [ - { - "dataset": "access", - "index_pattern": "logs-azure_frontdoor.access-*", - "title": "FrontDoor Access" - }, - { - "dataset": "waf", - "index_pattern": "logs-azure_frontdoor.waf-*", - "title": "FrontDoor WAF" - } - ], - "elser_embedding": "Azure Frontdoor - This Elastic integration collects logs from Azure Frontdoor. - FrontDoor Access FrontDoor WAF" - }, - { - "title": "Amazon Data Firehose", - "id": "awsfirehose", - "description": "Stream logs and metrics from Amazon Data Firehose into Elastic Cloud.", - "data_streams": [ - { - "dataset": "logs", - "index_pattern": "logs-awsfirehose.logs-*", - "title": "Logs from Amazon Data Firehose" - }, - { - "dataset": "metrics", - "index_pattern": "logs-awsfirehose.metrics-*", - "title": "Metrics ingested from Amazon Data Firehose" - } - ], - "elser_embedding": "Amazon Data Firehose - Stream logs and metrics from Amazon Data Firehose into Elastic Cloud. - Logs from Amazon Data Firehose Metrics ingested from Amazon Data Firehose" - }, - { - "title": "Zscaler Internet Access", - "id": "zscaler_zia", - "description": "Collect logs from Zscaler Internet Access (ZIA) with Elastic Agent.", - "data_streams": [ - { - "dataset": "sandbox_report", - "index_pattern": "logs-zscaler_zia.sandbox_report-*", - "title": "Sandbox Report Logs" - }, - { - "dataset": "tunnel", - "index_pattern": "logs-zscaler_zia.tunnel-*", - "title": "Tunnel Logs" - }, - { - "dataset": "audit", - "index_pattern": "logs-zscaler_zia.audit-*", - "title": "Audit Logs" - }, - { - "dataset": "dns", - "index_pattern": "logs-zscaler_zia.dns-*", - "title": "DNS logs" - }, - { - "dataset": "web", - "index_pattern": "logs-zscaler_zia.web-*", - "title": "Web Logs" - }, - { - "dataset": "endpoint_dlp", - "index_pattern": "logs-zscaler_zia.endpoint_dlp-*", - "title": "Endpoint DLP Logs" - }, - { - "dataset": "alerts", - "index_pattern": "logs-zscaler_zia.alerts-*", - "title": "Alerts" - }, - { - "dataset": "firewall", - "index_pattern": "logs-zscaler_zia.firewall-*", - "title": "Firewall Logs" - } - ], - "elser_embedding": "Zscaler Internet Access - Collect logs from Zscaler Internet Access (ZIA) with Elastic Agent. - Sandbox Report Logs Tunnel Logs Audit Logs DNS logs Web Logs Endpoint DLP Logs Alerts Firewall Logs" - }, - { - "title": "Broadcom ProxySG", - "id": "proxysg", - "description": "Collect access logs from Broadcom ProxySG with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-proxysg.log-*", - "title": "ProxySG Access Logs" - } - ], - "elser_embedding": "Broadcom ProxySG - Collect access logs from Broadcom ProxySG with Elastic Agent. - ProxySG Access Logs" - }, - { - "title": "Juniper SRX", - "id": "juniper_srx", - "description": "Collect logs from Juniper SRX devices with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-juniper_srx.log-*", - "title": "Juniper SRX logs" - } - ], - "elser_embedding": "Juniper SRX - Collect logs from Juniper SRX devices with Elastic Agent. - Juniper SRX logs" - }, - { - "title": "ServiceNow", - "id": "servicenow", - "description": "Collect logs from ServiceNow with Elastic Agent.", - "data_streams": [ - { - "dataset": "event", - "index_pattern": "logs-servicenow.event-*", - "title": "Event" - } - ], - "elser_embedding": "ServiceNow - Collect logs from ServiceNow with Elastic Agent. - Event" - }, - { - "title": "Defend for Containers", - "id": "cloud_defend", - "description": "Elastic Defend for Containers (BETA) provides cloud-native runtime protections for containerized environments.", - "data_streams": [ - { - "dataset": "heartbeat", - "index_pattern": "logs-cloud_defend.heartbeat-*", - "title": "Cloud Defend Liveness Heartbeat" - }, - { - "dataset": "file", - "index_pattern": "logs-cloud_defend.file-*", - "title": "File telemetry" - }, - { - "dataset": "process", - "index_pattern": "logs-cloud_defend.process-*", - "title": "Process telemetry" - }, - { - "dataset": "metrics", - "index_pattern": "logs-cloud_defend.metrics-*", - "title": "Cloud defend metrics" - }, - { - "dataset": "alerts", - "index_pattern": "logs-cloud_defend.alerts-*", - "title": "alerts" - } - ], - "elser_embedding": "Defend for Containers - Elastic Defend for Containers (BETA) provides cloud-native runtime protections for containerized environments. - Cloud Defend Liveness Heartbeat File telemetry Process telemetry Cloud defend metrics alerts" - }, - { - "title": "authentik", - "id": "authentik", - "description": "Collect logs from authentik with Elastic Agent.", - "data_streams": [ - { - "dataset": "group", - "index_pattern": "logs-authentik.group-*", - "title": "authentik group logs" - }, - { - "dataset": "event", - "index_pattern": "logs-authentik.event-*", - "title": "authentik event logs" - }, - { - "dataset": "user", - "index_pattern": "logs-authentik.user-*", - "title": "authentik user logs" - } - ], - "elser_embedding": "authentik - Collect logs from authentik with Elastic Agent. - authentik group logs authentik event logs authentik user logs" - }, - { - "title": "Wiz", - "id": "wiz", - "description": "Collect logs from Wiz with Elastic Agent.", - "data_streams": [ - { - "dataset": "issue", - "index_pattern": "logs-wiz.issue-*", - "title": "Collect Issue logs from Wiz." - }, - { - "dataset": "vulnerability", - "index_pattern": "logs-wiz.vulnerability-*", - "title": "Collect Vulnerability logs from Wiz." - }, - { - "dataset": "audit", - "index_pattern": "logs-wiz.audit-*", - "title": "Collect Audit logs from Wiz." - }, - { - "dataset": "cloud_configuration_finding", - "index_pattern": "logs-wiz.cloud_configuration_finding-*", - "title": "Collet Cloud Configuration Finding logs from Wiz." - } - ], - "elser_embedding": "Wiz - Collect logs from Wiz with Elastic Agent. - Collect Issue logs from Wiz. Collect Vulnerability logs from Wiz. Collect Audit logs from Wiz. Collet Cloud Configuration Finding logs from Wiz." - }, - { - "title": "Mattermost", - "id": "mattermost", - "description": "Collect logs from Mattermost with Elastic Agent.", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-mattermost.audit-*", - "title": "Audit Logs" - } - ], - "elser_embedding": "Mattermost - Collect logs from Mattermost with Elastic Agent. - Audit Logs" - }, - { - "title": "Teleport", - "id": "teleport", - "description": "Collect logs from Teleport with Elastic Agent.", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-teleport.audit-*", - "title": "Teleport audit logs" - } - ], - "elser_embedding": "Teleport - Collect logs from Teleport with Elastic Agent. - Teleport audit logs" - }, - { - "title": "Fleet Server", - "id": "fleet_server", - "description": "Centrally manage Elastic Agents with the Fleet Server integration.", - "data_streams": [ - { - "dataset": "agent_versions_metrics", - "index_pattern": "logs-fleet_server.agent_versions_metrics-*", - "title": "Fleet Agent Versions" - }, - { - "dataset": "agent_status_metrics", - "index_pattern": "logs-fleet_server.agent_status_metrics-*", - "title": "Fleet Agent Status" - }, - { - "dataset": "output_health_logs", - "index_pattern": "logs-fleet_server.output_health_logs-*", - "title": "Output Health" - } - ], - "elser_embedding": "Fleet Server - Centrally manage Elastic Agents with the Fleet Server integration. - Fleet Agent Versions Fleet Agent Status Output Health" - }, - { - "title": "Cisco Secure Endpoint", - "id": "cisco_secure_endpoint", - "description": "Collect logs from Cisco Secure Endpoint (AMP) with Elastic Agent.", - "data_streams": [ - { - "dataset": "event", - "index_pattern": "logs-cisco_secure_endpoint.event-*", - "title": "Cisco Secure Endpoint logs" - } - ], - "elser_embedding": "Cisco Secure Endpoint - Collect logs from Cisco Secure Endpoint (AMP) with Elastic Agent. - Cisco Secure Endpoint logs" - }, - { - "title": "Iptables", - "id": "iptables", - "description": "Collect logs from Iptables with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-iptables.log-*", - "title": "Iptables log logs" - } - ], - "elser_embedding": "Iptables - Collect logs from Iptables with Elastic Agent. - Iptables log logs" - }, - { - "title": "Google Workspace", - "id": "google_workspace", - "description": "Collect logs from Google Workspace with Elastic Agent.", - "data_streams": [ - { - "dataset": "user_accounts", - "index_pattern": "logs-google_workspace.user_accounts-*", - "title": "User accounts logs" - }, - { - "dataset": "device", - "index_pattern": "logs-google_workspace.device-*", - "title": "Device logs" - }, - { - "dataset": "admin", - "index_pattern": "logs-google_workspace.admin-*", - "title": "Admin logs" - }, - { - "dataset": "gcp", - "index_pattern": "logs-google_workspace.gcp-*", - "title": "GCP logs" - }, - { - "dataset": "group_enterprise", - "index_pattern": "logs-google_workspace.group_enterprise-*", - "title": "Group Enterprise logs" - }, - { - "dataset": "login", - "index_pattern": "logs-google_workspace.login-*", - "title": "Login logs" - }, - { - "dataset": "access_transparency", - "index_pattern": "logs-google_workspace.access_transparency-*", - "title": "Access Transparency logs" - }, - { - "dataset": "alert", - "index_pattern": "logs-google_workspace.alert-*", - "title": "Collect Alert logs from Google Workspace" - }, - { - "dataset": "context_aware_access", - "index_pattern": "logs-google_workspace.context_aware_access-*", - "title": "Context Aware Access logs" - }, - { - "dataset": "token", - "index_pattern": "logs-google_workspace.token-*", - "title": "Token logs" - }, - { - "dataset": "drive", - "index_pattern": "logs-google_workspace.drive-*", - "title": "Drive logs" - }, - { - "dataset": "groups", - "index_pattern": "logs-google_workspace.groups-*", - "title": "Groups logs" - }, - { - "dataset": "saml", - "index_pattern": "logs-google_workspace.saml-*", - "title": "SAML logs" - }, - { - "dataset": "rules", - "index_pattern": "logs-google_workspace.rules-*", - "title": "Rules logs" - } - ], - "elser_embedding": "Google Workspace - Collect logs from Google Workspace with Elastic Agent. - User accounts logs Device logs Admin logs GCP logs Group Enterprise logs Login logs Access Transparency logs Collect Alert logs from Google Workspace Context Aware Access logs Token logs Drive logs Groups logs SAML logs Rules logs" - }, - { - "title": "VMware Carbon Black EDR", - "id": "carbonblack_edr", - "description": "Collect logs from VMware Carbon Black EDR with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-carbonblack_edr.log-*", - "title": "Carbon Black EDR logs" - } - ], - "elser_embedding": "VMware Carbon Black EDR - Collect logs from VMware Carbon Black EDR with Elastic Agent. - Carbon Black EDR logs" - }, - { - "title": "Mimecast", - "id": "mimecast", - "description": "Collect logs from Mimecast with Elastic Agent.", - "data_streams": [ - { - "dataset": "dlp_logs", - "index_pattern": "logs-mimecast.dlp_logs-*", - "title": "DLP Mimecast Logs" - }, - { - "dataset": "ttp_url_logs", - "index_pattern": "logs-mimecast.ttp_url_logs-*", - "title": "TTP URL Logs" - }, - { - "dataset": "siem_logs", - "index_pattern": "logs-mimecast.siem_logs-*", - "title": "SIEM Mimecast Logs" - }, - { - "dataset": "message_release_logs", - "index_pattern": "logs-mimecast.message_release_logs-*", - "title": "Mimecast Message Release" - }, - { - "dataset": "ttp_ip_logs", - "index_pattern": "logs-mimecast.ttp_ip_logs-*", - "title": "TTP Impersonation Mimecast Logs" - }, - { - "dataset": "audit_events", - "index_pattern": "logs-mimecast.audit_events-*", - "title": "Audit Events Mimecast Logs" - }, - { - "dataset": "ttp_ap_logs", - "index_pattern": "logs-mimecast.ttp_ap_logs-*", - "title": "TTP Attachment Logs" - }, - { - "dataset": "archive_search_logs", - "index_pattern": "logs-mimecast.archive_search_logs-*", - "title": "Archive Search Mimecast Logs" - }, - { - "dataset": "threat_intel_malware_grid", - "index_pattern": "logs-mimecast.threat_intel_malware_grid-*", - "title": "Threat Intel Feed - Malware Grid" - }, - { - "dataset": "threat_intel_malware_customer", - "index_pattern": "logs-mimecast.threat_intel_malware_customer-*", - "title": "Threat Intel Feed - Malware Customer" - } - ], - "elser_embedding": "Mimecast - Collect logs from Mimecast with Elastic Agent. - DLP Mimecast Logs TTP URL Logs SIEM Mimecast Logs Mimecast Message Release TTP Impersonation Mimecast Logs Audit Events Mimecast Logs TTP Attachment Logs Archive Search Mimecast Logs Threat Intel Feed - Malware Grid Threat Intel Feed - Malware Customer" - }, - { - "title": "Oracle WebLogic", - "id": "oracle_weblogic", - "description": "Collect logs and metrics from Oracle WebLogic with Elastic Agent.", - "data_streams": [ - { - "dataset": "managed_server", - "index_pattern": "logs-oracle_weblogic.managed_server-*", - "title": "Managed Server logs" - }, - { - "dataset": "access", - "index_pattern": "logs-oracle_weblogic.access-*", - "title": "Access logs" - }, - { - "dataset": "threadpool", - "index_pattern": "logs-oracle_weblogic.threadpool-*", - "title": "Collect Oracle WebLogic ThreadPool metrics" - }, - { - "dataset": "deployed_application", - "index_pattern": "logs-oracle_weblogic.deployed_application-*", - "title": "Collect Oracle WebLogic Deployed Application metrics" - }, - { - "dataset": "admin_server", - "index_pattern": "logs-oracle_weblogic.admin_server-*", - "title": "Admin Server logs" - }, - { - "dataset": "domain", - "index_pattern": "logs-oracle_weblogic.domain-*", - "title": "Domain logs" - } - ], - "elser_embedding": "Oracle WebLogic - Collect logs and metrics from Oracle WebLogic with Elastic Agent. - Managed Server logs Access logs Collect Oracle WebLogic ThreadPool metrics Collect Oracle WebLogic Deployed Application metrics Admin Server logs Domain logs" - }, - { - "title": "System Audit", - "id": "system_audit", - "description": "Collect various logs & metrics from System Audit modules with Elastic Agent.", - "data_streams": [ - { - "dataset": "package", - "index_pattern": "logs-system_audit.package-*", - "title": "System Audit - [Package]" - } - ], - "elser_embedding": "System Audit - Collect various logs & metrics from System Audit modules with Elastic Agent. - System Audit - [Package]" - }, - { - "title": "Salesforce", - "id": "salesforce", - "description": "Collect logs from Salesforce instances using the Elastic Agent. This integration enables monitoring and analysis of various Salesforce logs, including Login, Logout, Setup Audit Trail, and Apex execution logs. Gain insights into user activity, security events, and application performance.\n", - "data_streams": [ - { - "dataset": "setupaudittrail", - "index_pattern": "logs-salesforce.setupaudittrail-*", - "title": "Salesforce setupaudittrail logs" - }, - { - "dataset": "login", - "index_pattern": "logs-salesforce.login-*", - "title": "Salesforce login logs" - }, - { - "dataset": "logout", - "index_pattern": "logs-salesforce.logout-*", - "title": "Salesforce logout logs" - }, - { - "dataset": "apex", - "index_pattern": "logs-salesforce.apex-*", - "title": "Salesforce Apex logs" - } - ], - "elser_embedding": "Salesforce - Collect logs from Salesforce instances using the Elastic Agent. This integration enables monitoring and analysis of various Salesforce logs, including Login, Logout, Setup Audit Trail, and Apex execution logs. Gain insights into user activity, security events, and application performance.\n - Salesforce setupaudittrail logs Salesforce login logs Salesforce logout logs Salesforce Apex logs" - }, - { - "title": "Azure Application Insights Metrics Overview", - "id": "azure_application_insights", - "description": "Collect application insights metrics from Azure Monitor with Elastic Agent.", - "data_streams": [ - { - "dataset": "app_insights", - "index_pattern": "logs-azure_application_insights.app_insights-*", - "title": "Azure Application Insights" - }, - { - "dataset": "app_state", - "index_pattern": "logs-azure_application_insights.app_state-*", - "title": "Azure Application State" - } - ], - "elser_embedding": "Azure Application Insights Metrics Overview - Collect application insights metrics from Azure Monitor with Elastic Agent. - Azure Application Insights Azure Application State" - }, - { - "title": "ForgeRock", - "id": "forgerock", - "description": "Collect audit logs from ForgeRock with Elastic Agent.", - "data_streams": [ - { - "dataset": "idm_sync", - "index_pattern": "logs-forgerock.idm_sync-*", - "title": "IDM-Sync audit logs" - }, - { - "dataset": "idm_core", - "index_pattern": "logs-forgerock.idm_core-*", - "title": "IDM-Core debug logs" - }, - { - "dataset": "am_access", - "index_pattern": "logs-forgerock.am_access-*", - "title": "AM-Access audit logs" - }, - { - "dataset": "idm_activity", - "index_pattern": "logs-forgerock.idm_activity-*", - "title": "IDM-Activity audit logs" - }, - { - "dataset": "idm_config", - "index_pattern": "logs-forgerock.idm_config-*", - "title": "IDM-Config audit logs" - }, - { - "dataset": "am_config", - "index_pattern": "logs-forgerock.am_config-*", - "title": "AM-Config audit logs" - }, - { - "dataset": "am_activity", - "index_pattern": "logs-forgerock.am_activity-*", - "title": "AM-Activity audit logs" - }, - { - "dataset": "am_authentication", - "index_pattern": "logs-forgerock.am_authentication-*", - "title": "AM-Authentication audit logs" - }, - { - "dataset": "idm_authentication", - "index_pattern": "logs-forgerock.idm_authentication-*", - "title": "IDM-Authentication audit logs" - }, - { - "dataset": "idm_access", - "index_pattern": "logs-forgerock.idm_access-*", - "title": "IDM-Access audit logs" - }, - { - "dataset": "am_core", - "index_pattern": "logs-forgerock.am_core-*", - "title": "AM-Core debug logs" - } - ], - "elser_embedding": "ForgeRock - Collect audit logs from ForgeRock with Elastic Agent. - IDM-Sync audit logs IDM-Core debug logs AM-Access audit logs IDM-Activity audit logs IDM-Config audit logs AM-Config audit logs AM-Activity audit logs AM-Authentication audit logs IDM-Authentication audit logs IDM-Access audit logs AM-Core debug logs" - }, - { - "title": "Tenable.sc", - "id": "tenable_sc", - "description": "Collect logs from Tenable.sc with Elastic Agent.\n", - "data_streams": [ - { - "dataset": "plugin", - "index_pattern": "logs-tenable_sc.plugin-*", - "title": "Tenable.sc plugin logs" - }, - { - "dataset": "vulnerability", - "index_pattern": "logs-tenable_sc.vulnerability-*", - "title": "Tenable.sc vulnerability logs" - }, - { - "dataset": "asset", - "index_pattern": "logs-tenable_sc.asset-*", - "title": "Tenable.sc asset logs" - } - ], - "elser_embedding": "Tenable.sc - Collect logs from Tenable.sc with Elastic Agent.\n - Tenable.sc plugin logs Tenable.sc vulnerability logs Tenable.sc asset logs" - }, - { - "title": "Cisco IOS", - "id": "cisco_ios", - "description": "Collect logs from Cisco IOS with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-cisco_ios.log-*", - "title": "Cisco IOS logs" - } - ], - "elser_embedding": "Cisco IOS - Collect logs from Cisco IOS with Elastic Agent. - Cisco IOS logs" - }, - { - "title": "ZooKeeper Metrics", - "id": "zookeeper", - "description": "Collect metrics from ZooKeeper service with Elastic Agent.", - "data_streams": [ - { - "dataset": "connection", - "index_pattern": "logs-zookeeper.connection-*", - "title": "ZooKeeper connection metrics" - }, - { - "dataset": "mntr", - "index_pattern": "logs-zookeeper.mntr-*", - "title": "ZooKeeper mntr metrics" - }, - { - "dataset": "server", - "index_pattern": "logs-zookeeper.server-*", - "title": "ZooKeeper server metrics" - } - ], - "elser_embedding": "ZooKeeper Metrics - Collect metrics from ZooKeeper service with Elastic Agent. - ZooKeeper connection metrics ZooKeeper mntr metrics ZooKeeper server metrics" - }, - { - "title": "Palo Alto Next-Gen Firewall", - "id": "panw", - "description": "Collect logs from Palo Alto next-gen firewalls with Elastic Agent.", - "data_streams": [ - { - "dataset": "panos", - "index_pattern": "logs-panw.panos-*", - "title": "Palo Alto Networks PAN-OS firewall logs" - } - ], - "elser_embedding": "Palo Alto Next-Gen Firewall - Collect logs from Palo Alto next-gen firewalls with Elastic Agent. - Palo Alto Networks PAN-OS firewall logs" - }, - { - "title": "Hadoop", - "id": "hadoop", - "description": "Collect metrics from Apache Hadoop with Elastic Agent.", - "data_streams": [ - { - "dataset": "namenode", - "index_pattern": "logs-hadoop.namenode-*", - "title": "NameNode Metrics" - }, - { - "dataset": "datanode", - "index_pattern": "logs-hadoop.datanode-*", - "title": "DataNode metrics" - }, - { - "dataset": "node_manager", - "index_pattern": "logs-hadoop.node_manager-*", - "title": "Node Manager metrics" - }, - { - "dataset": "application", - "index_pattern": "logs-hadoop.application-*", - "title": "Application metrics" - }, - { - "dataset": "cluster", - "index_pattern": "logs-hadoop.cluster-*", - "title": "Cluster metrics" - } - ], - "elser_embedding": "Hadoop - Collect metrics from Apache Hadoop with Elastic Agent. - NameNode Metrics DataNode metrics Node Manager metrics Application metrics Cluster metrics" - }, - { - "title": "InfluxDb", - "id": "influxdb", - "description": "Collect metrics from Influxdb database", - "data_streams": [ - { - "dataset": "advstatus", - "index_pattern": "logs-influxdb.advstatus-*", - "title": "InfluxDB database advanced status metrics" - }, - { - "dataset": "status", - "index_pattern": "logs-influxdb.status-*", - "title": "InfluxDB database status metrics" - } - ], - "elser_embedding": "InfluxDb - Collect metrics from Influxdb database - InfluxDB database advanced status metrics InfluxDB database status metrics" - }, - { - "title": "Sophos", - "id": "sophos", - "description": "Collect logs from Sophos with Elastic Agent.", - "data_streams": [ - { - "dataset": "xg", - "index_pattern": "logs-sophos.xg-*", - "title": "Sophos XG logs" - }, - { - "dataset": "utm", - "index_pattern": "logs-sophos.utm-*", - "title": "Sophos UTM logs" - } - ], - "elser_embedding": "Sophos - Collect logs from Sophos with Elastic Agent. - Sophos XG logs Sophos UTM logs" - }, - { - "title": "Menlo Security", - "id": "menlo", - "description": "Collect logs from Menlo Security products with Elastic Agent", - "data_streams": [ - { - "dataset": "dlp", - "index_pattern": "logs-menlo.dlp-*", - "title": "Collect Menlo DLP from Menlo Security API" - }, - { - "dataset": "web", - "index_pattern": "logs-menlo.web-*", - "title": "Collect Menlo Web from Menlo Security API" - } - ], - "elser_embedding": "Menlo Security - Collect logs from Menlo Security products with Elastic Agent - Collect Menlo DLP from Menlo Security API Collect Menlo Web from Menlo Security API" - }, - { - "title": "Barracuda Web Application Firewall", - "id": "barracuda", - "description": "Collect logs from Barracuda Web Application Firewall with Elastic Agent.", - "data_streams": [ - { - "dataset": "waf", - "index_pattern": "logs-barracuda.waf-*", - "title": "Barracuda WAF Logs" - } - ], - "elser_embedding": "Barracuda Web Application Firewall - Collect logs from Barracuda Web Application Firewall with Elastic Agent. - Barracuda WAF Logs" - }, - { - "title": "FireEye Network Security", - "id": "fireeye", - "description": "Collect logs from FireEye NX with Elastic Agent.", - "data_streams": [ - { - "dataset": "nx", - "index_pattern": "logs-fireeye.nx-*", - "title": "Fireeye NX" - } - ], - "elser_embedding": "FireEye Network Security - Collect logs from FireEye NX with Elastic Agent. - Fireeye NX" - }, - { - "title": "Tines", - "id": "tines", - "description": "Tines Logs & Time Saved Reports", - "data_streams": [ - { - "dataset": "time_saved", - "index_pattern": "logs-tines.time_saved-*", - "title": "Tines Time Saved Reports" - }, - { - "dataset": "audit_logs", - "index_pattern": "logs-tines.audit_logs-*", - "title": "Tines Audit Logs" - } - ], - "elser_embedding": "Tines - Tines Logs & Time Saved Reports - Tines Time Saved Reports Tines Audit Logs" - }, - { - "title": "Cisco Meraki Metrics", - "id": "cisco_meraki_metrics", - "description": "Collect metrics from Cisco Meraki with Elastic Agent.", - "data_streams": [ - { - "dataset": "device_health", - "index_pattern": "logs-cisco_meraki_metrics.device_health-*", - "title": "Cisco Meraki Device Health Metrics" - } - ], - "elser_embedding": "Cisco Meraki Metrics - Collect metrics from Cisco Meraki with Elastic Agent. - Cisco Meraki Device Health Metrics" - }, - { - "title": "VMware vSphere", - "id": "vsphere", - "description": "This Elastic integration collects metrics and logs from vSphere/vCenter servers", - "data_streams": [ - { - "dataset": "network", - "index_pattern": "logs-vsphere.network-*", - "title": "vSphere network metrics" - }, - { - "dataset": "resourcepool", - "index_pattern": "logs-vsphere.resourcepool-*", - "title": "vSphere resourcepool metrics" - }, - { - "dataset": "datastore", - "index_pattern": "logs-vsphere.datastore-*", - "title": "vSphere datastore metrics" - }, - { - "dataset": "virtualmachine", - "index_pattern": "logs-vsphere.virtualmachine-*", - "title": "vSphere virtual machine metrics" - }, - { - "dataset": "host", - "index_pattern": "logs-vsphere.host-*", - "title": "vSphere host metrics" - }, - { - "dataset": "datastorecluster", - "index_pattern": "logs-vsphere.datastorecluster-*", - "title": "vSphere DatastoreCluster metrics" - }, - { - "dataset": "log", - "index_pattern": "logs-vsphere.log-*", - "title": "vSphere Logs" - }, - { - "dataset": "cluster", - "index_pattern": "logs-vsphere.cluster-*", - "title": "vSphere cluster metrics" - } - ], - "elser_embedding": "VMware vSphere - This Elastic integration collects metrics and logs from vSphere/vCenter servers - vSphere network metrics vSphere resourcepool metrics vSphere datastore metrics vSphere virtual machine metrics vSphere host metrics vSphere DatastoreCluster metrics vSphere Logs vSphere cluster metrics" - }, - { - "title": "Platform Observability", - "id": "platform_observability", - "description": "Collect stack component logs with Elastic Agent", - "data_streams": [ - { - "dataset": "kibana_audit", - "index_pattern": "logs-platform_observability.kibana_audit-*", - "title": "Platform Observability Kibana audit logs" - }, - { - "dataset": "kibana_log", - "index_pattern": "logs-platform_observability.kibana_log-*", - "title": "Platform Observability Kibana logs" - } - ], - "elser_embedding": "Platform Observability - Collect stack component logs with Elastic Agent - Platform Observability Kibana audit logs Platform Observability Kibana logs" - }, - { - "title": "System", - "id": "system", - "description": "Collect system logs and metrics from your servers with Elastic Agent.", - "data_streams": [ - { - "dataset": "memory", - "index_pattern": "logs-system.memory-*", - "title": "System memory metrics" - }, - { - "dataset": "network", - "index_pattern": "logs-system.network-*", - "title": "System network metrics" - }, - { - "dataset": "uptime", - "index_pattern": "logs-system.uptime-*", - "title": "System uptime metrics" - }, - { - "dataset": "socket_summary", - "index_pattern": "logs-system.socket_summary-*", - "title": "System socket_summary metrics" - }, - { - "dataset": "auth", - "index_pattern": "logs-system.auth-*", - "title": "System auth logs" - }, - { - "dataset": "process", - "index_pattern": "logs-system.process-*", - "title": "System process metrics" - }, - { - "dataset": "load", - "index_pattern": "logs-system.load-*", - "title": "System load metrics" - }, - { - "dataset": "application", - "index_pattern": "logs-system.application-*", - "title": "Windows Application Events" - }, - { - "dataset": "diskio", - "index_pattern": "logs-system.diskio-*", - "title": "System diskio metrics" - }, - { - "dataset": "syslog", - "index_pattern": "logs-system.syslog-*", - "title": "System syslog logs" - }, - { - "dataset": "filesystem", - "index_pattern": "logs-system.filesystem-*", - "title": "System filesystem metrics" - }, - { - "dataset": "fsstat", - "index_pattern": "logs-system.fsstat-*", - "title": "System fsstat metrics" - }, - { - "dataset": "core", - "index_pattern": "logs-system.core-*", - "title": "System core metrics" - }, - { - "dataset": "cpu", - "index_pattern": "logs-system.cpu-*", - "title": "System cpu metrics" - }, - { - "dataset": "process_summary", - "index_pattern": "logs-system.process_summary-*", - "title": "System process_summary metrics" - }, - { - "dataset": "system", - "index_pattern": "logs-system.system-*", - "title": "Windows System Events" - }, - { - "dataset": "security", - "index_pattern": "logs-system.security-*", - "title": "Security logs" - } - ], - "elser_embedding": "System - Collect system logs and metrics from your servers with Elastic Agent. - System memory metrics System network metrics System uptime metrics System socket_summary metrics System auth logs System process metrics System load metrics Windows Application Events System diskio metrics System syslog logs System filesystem metrics System fsstat metrics System core metrics System cpu metrics System process_summary metrics Windows System Events Security logs" - }, - { - "title": "Airflow", - "id": "airflow", - "description": "Airflow Integration.", - "data_streams": [ - { - "dataset": "statsd", - "index_pattern": "logs-airflow.statsd-*", - "title": "Airflow metrics" - } - ], - "elser_embedding": "Airflow - Airflow Integration. - Airflow metrics" - }, - { - "title": "Custom Google Pub/Sub Logs", - "id": "gcp_pubsub", - "description": "Collect Logs from Google Pub/Sub topics", - "data_streams": [], - "elser_embedding": "Custom Google Pub/Sub Logs - Collect Logs from Google Pub/Sub topics - " - }, - { - "title": "Beat", - "id": "beat", - "description": "Beat Integration", - "data_streams": [], - "elser_embedding": "Beat - Beat Integration - " - }, - { - "title": "Cyberark Privileged Threat Analytics", - "id": "cyberark_pta", - "description": "Collect security logs from Cyberark PTA integration.", - "data_streams": [ - { - "dataset": "events", - "index_pattern": "logs-cyberark_pta.events-*", - "title": "CyberArk PTA logs" - } - ], - "elser_embedding": "Cyberark Privileged Threat Analytics - Collect security logs from Cyberark PTA integration. - CyberArk PTA logs" - }, - { - "title": "Trellix ePO Cloud", - "id": "trellix_epo_cloud", - "description": "Collect logs from Trellix ePO Cloud with Elastic Agent.", - "data_streams": [ - { - "dataset": "device", - "index_pattern": "logs-trellix_epo_cloud.device-*", - "title": "Collect Device logs from Trellix ePO Cloud." - }, - { - "dataset": "group", - "index_pattern": "logs-trellix_epo_cloud.group-*", - "title": "Collect Group logs from Trellix ePO Cloud." - }, - { - "dataset": "event", - "index_pattern": "logs-trellix_epo_cloud.event-*", - "title": "Collect Event logs from Trellix ePO Cloud." - } - ], - "elser_embedding": "Trellix ePO Cloud - Collect logs from Trellix ePO Cloud with Elastic Agent. - Collect Device logs from Trellix ePO Cloud. Collect Group logs from Trellix ePO Cloud. Collect Event logs from Trellix ePO Cloud." - }, - { - "title": "Vectra Detect", - "id": "vectra_detect", - "description": "Collect logs from Vectra Detect with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-vectra_detect.log-*", - "title": "Collect logs from Vectra Detect" - } - ], - "elser_embedding": "Vectra Detect - Collect logs from Vectra Detect with Elastic Agent. - Collect logs from Vectra Detect" - }, - { - "title": "Atlassian Confluence", - "id": "atlassian_confluence", - "description": "Collect logs from Atlassian Confluence with Elastic Agent.", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-atlassian_confluence.audit-*", - "title": "Confluence Audit Logs" - } - ], - "elser_embedding": "Atlassian Confluence - Collect logs from Atlassian Confluence with Elastic Agent. - Confluence Audit Logs" - }, - { - "title": "QNAP NAS", - "id": "qnap_nas", - "description": "Collect logs from QNAP NAS devices with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-qnap_nas.log-*", - "title": "QNAP NAS logs" - } - ], - "elser_embedding": "QNAP NAS - Collect logs from QNAP NAS devices with Elastic Agent. - QNAP NAS logs" - }, - { - "title": "Memcached", - "id": "memcached", - "description": "Memcached Integration", - "data_streams": [ - { - "dataset": "stats", - "index_pattern": "logs-memcached.stats-*", - "title": "Memcached stats metrics" - } - ], - "elser_embedding": "Memcached - Memcached Integration - Memcached stats metrics" - }, - { - "title": "Azure Resource Metrics", - "id": "azure_metrics", - "description": "Collect metrics from Azure resources with Elastic Agent.", - "data_streams": [ - { - "dataset": "container_service", - "index_pattern": "logs-azure_metrics.container_service-*", - "title": "Container Service" - }, - { - "dataset": "container_instance", - "index_pattern": "logs-azure_metrics.container_instance-*", - "title": "Container Instance" - }, - { - "dataset": "compute_vm", - "index_pattern": "logs-azure_metrics.compute_vm-*", - "title": "Compute VM" - }, - { - "dataset": "monitor", - "index_pattern": "logs-azure_metrics.monitor-*", - "title": "Monitor" - }, - { - "dataset": "storage_account", - "index_pattern": "logs-azure_metrics.storage_account-*", - "title": "Storage Account" - }, - { - "dataset": "compute_vm_scaleset", - "index_pattern": "logs-azure_metrics.compute_vm_scaleset-*", - "title": "Compute VM Scaleset" - }, - { - "dataset": "database_account", - "index_pattern": "logs-azure_metrics.database_account-*", - "title": "Database Account" - }, - { - "dataset": "container_registry", - "index_pattern": "logs-azure_metrics.container_registry-*", - "title": "Container Registry" - } - ], - "elser_embedding": "Azure Resource Metrics - Collect metrics from Azure resources with Elastic Agent. - Container Service Container Instance Compute VM Monitor Storage Account Compute VM Scaleset Database Account Container Registry" - }, - { - "title": "Elastic Connectors", - "id": "elastic_connectors", - "description": "Sync data from source to the Elasticsearch index.", - "data_streams": [], - "elser_embedding": "Elastic Connectors - Sync data from source to the Elasticsearch index. - " - }, - { - "title": "StatsD Input", - "id": "statsd_input", - "description": "StatsD Input Package", - "data_streams": [], - "elser_embedding": "StatsD Input - StatsD Input Package - " - }, - { - "title": "Cloudflare", - "id": "cloudflare", - "description": "Collect logs from Cloudflare with Elastic Agent.", - "data_streams": [ - { - "dataset": "logpull", - "index_pattern": "logs-cloudflare.logpull-*", - "title": "Cloudflare Logpull" - }, - { - "dataset": "audit", - "index_pattern": "logs-cloudflare.audit-*", - "title": "Cloudflare Audit Logs" - } - ], - "elser_embedding": "Cloudflare - Collect logs from Cloudflare with Elastic Agent. - Cloudflare Logpull Cloudflare Audit Logs" - }, - { - "title": "Cribl", - "id": "cribl", - "description": "Stream logs from Cribl into Elastic.", - "data_streams": [ - { - "dataset": "logs", - "index_pattern": "logs-cribl.logs-*", - "title": "Logs" - } - ], - "elser_embedding": "Cribl - Stream logs from Cribl into Elastic. - Logs" - }, - { - "title": "PHP-FPM", - "id": "php_fpm", - "description": "This Elastic integration collects metrics from PHP-FPM.", - "data_streams": [ - { - "dataset": "process", - "index_pattern": "logs-php_fpm.process-*", - "title": "Process metrics" - }, - { - "dataset": "pool", - "index_pattern": "logs-php_fpm.pool-*", - "title": "Pool metrics" - } - ], - "elser_embedding": "PHP-FPM - This Elastic integration collects metrics from PHP-FPM. - Process metrics Pool metrics" - }, - { - "title": "Azure Logs", - "id": "azure", - "description": "This Elastic integration collects logs from Azure", - "data_streams": [ - { - "dataset": "platformlogs", - "index_pattern": "logs-azure.platformlogs-*", - "title": "Azure Platform Logs" - }, - { - "dataset": "auditlogs", - "index_pattern": "logs-azure.auditlogs-*", - "title": "Azure Audit Logs" - }, - { - "dataset": "springcloudlogs", - "index_pattern": "logs-azure.springcloudlogs-*", - "title": "Azure Spring Apps Logs" - }, - { - "dataset": "signinlogs", - "index_pattern": "logs-azure.signinlogs-*", - "title": "Azure Signin Logs" - }, - { - "dataset": "firewall_logs", - "index_pattern": "logs-azure.firewall_logs-*", - "title": "Collect Network rule logs from Azure Firewall" - }, - { - "dataset": "graphactivitylogs", - "index_pattern": "logs-azure.graphactivitylogs-*", - "title": "Microsoft Graph Activity Logs" - }, - { - "dataset": "application_gateway", - "index_pattern": "logs-azure.application_gateway-*", - "title": "Azure Application Gateway logs" - }, - { - "dataset": "eventhub", - "index_pattern": "logs-azure.eventhub-*", - "title": "Azure Event Hub Input" - }, - { - "dataset": "provisioning", - "index_pattern": "logs-azure.provisioning-*", - "title": "Microsoft Entra ID Provisioning Logs" - }, - { - "dataset": "activitylogs", - "index_pattern": "logs-azure.activitylogs-*", - "title": "Azure Activity Logs" - }, - { - "dataset": "identity_protection", - "index_pattern": "logs-azure.identity_protection-*", - "title": "Microsoft Entra ID Identity Protection Logs" - } - ], - "elser_embedding": "Azure Logs - This Elastic integration collects logs from Azure - Azure Platform Logs Azure Audit Logs Azure Spring Apps Logs Azure Signin Logs Collect Network rule logs from Azure Firewall Microsoft Graph Activity Logs Azure Application Gateway logs Azure Event Hub Input Microsoft Entra ID Provisioning Logs Azure Activity Logs Microsoft Entra ID Identity Protection Logs" - }, - { - "title": "Palo Alto Networks Metrics", - "id": "panw_metrics", - "description": "Collect metrics from Palo Alto Networks with Elastic Agent.", - "data_streams": [ - { - "dataset": "vpn", - "index_pattern": "logs-panw_metrics.vpn-*", - "title": "Palo Alto Networks VPN metrics" - }, - { - "dataset": "interfaces", - "index_pattern": "logs-panw_metrics.interfaces-*", - "title": "Palo Alto Networks Interfaces metrics" - }, - { - "dataset": "system", - "index_pattern": "logs-panw_metrics.system-*", - "title": "Palo Alto Networks System metrics" - }, - { - "dataset": "routing", - "index_pattern": "logs-panw_metrics.routing-*", - "title": "Palo Alto Networks Routing metrics" - } - ], - "elser_embedding": "Palo Alto Networks Metrics - Collect metrics from Palo Alto Networks with Elastic Agent. - Palo Alto Networks VPN metrics Palo Alto Networks Interfaces metrics Palo Alto Networks System metrics Palo Alto Networks Routing metrics" - }, - { - "title": "Custom Threat Intelligence", - "id": "ti_custom", - "description": "Ingest threat intelligence data in STIX 2.1 format with Elastic Agent", - "data_streams": [ - { - "dataset": "indicator", - "index_pattern": "logs-ti_custom.indicator-*", - "title": "STIX 2.1 indicators" - } - ], - "elser_embedding": "Custom Threat Intelligence - Ingest threat intelligence data in STIX 2.1 format with Elastic Agent - STIX 2.1 indicators" - }, - { - "title": "Check Point Harmony Endpoint", - "id": "checkpoint_harmony_endpoint", - "description": "Collect logs from Check Point Harmony Endpoint", - "data_streams": [ - { - "dataset": "urlfiltering", - "index_pattern": "logs-checkpoint_harmony_endpoint.urlfiltering-*", - "title": "URL Filtering" - }, - { - "dataset": "forensics", - "index_pattern": "logs-checkpoint_harmony_endpoint.forensics-*", - "title": "Forensics" - }, - { - "dataset": "antibot", - "index_pattern": "logs-checkpoint_harmony_endpoint.antibot-*", - "title": "Anti-Bot" - }, - { - "dataset": "threatemulation", - "index_pattern": "logs-checkpoint_harmony_endpoint.threatemulation-*", - "title": "Threat Emulation" - }, - { - "dataset": "threatextraction", - "index_pattern": "logs-checkpoint_harmony_endpoint.threatextraction-*", - "title": "Threat Extraction" - }, - { - "dataset": "zerophishing", - "index_pattern": "logs-checkpoint_harmony_endpoint.zerophishing-*", - "title": "Zero Phishing" - }, - { - "dataset": "antimalware", - "index_pattern": "logs-checkpoint_harmony_endpoint.antimalware-*", - "title": "Anti-Malware" - } - ], - "elser_embedding": "Check Point Harmony Endpoint - Collect logs from Check Point Harmony Endpoint - URL Filtering Forensics Anti-Bot Threat Emulation Threat Extraction Zero Phishing Anti-Malware" - }, - { - "title": "Thycotic Secret Server", - "id": "thycotic_ss", - "description": "Thycotic Secret Server logs", - "data_streams": [ - { - "dataset": "logs", - "index_pattern": "logs-thycotic_ss.logs-*", - "title": "Thycotic Secret Server Logs" - } - ], - "elser_embedding": "Thycotic Secret Server - Thycotic Secret Server logs - Thycotic Secret Server Logs" - }, - { - "title": "Custom HTTP Endpoint Logs", - "id": "http_endpoint", - "description": "Collect JSON data from listening HTTP port with Elastic Agent.", - "data_streams": [], - "elser_embedding": "Custom HTTP Endpoint Logs - Collect JSON data from listening HTTP port with Elastic Agent. - " - }, - { - "title": "Atlassian Bitbucket", - "id": "atlassian_bitbucket", - "description": "Collect logs from Atlassian Bitbucket with Elastic Agent.", - "data_streams": [ - { - "dataset": "audit", - "index_pattern": "logs-atlassian_bitbucket.audit-*", - "title": "Bitbucket Audit Logs" - } - ], - "elser_embedding": "Atlassian Bitbucket - Collect logs from Atlassian Bitbucket with Elastic Agent. - Bitbucket Audit Logs" - }, - { - "title": "TYCHON Agentless", - "id": "tychon", - "description": "Collect complete master endpoint datasets including vulnerability and STIG to comply with DISA endpoint requirements and C2C without adding services to your endpoints.", - "data_streams": [ - { - "dataset": "systemcerts", - "index_pattern": "logs-tychon.systemcerts-*", - "title": "System Certificates" - }, - { - "dataset": "stig", - "index_pattern": "logs-tychon.stig-*", - "title": "Endpoint STIG Results" - }, - { - "dataset": "softwareinventory", - "index_pattern": "logs-tychon.softwareinventory-*", - "title": "Endpoint Software Inventory Info" - }, - { - "dataset": "coams", - "index_pattern": "logs-tychon.coams-*", - "title": "Endpoint Operational Attributes (Requires DATT)" - }, - { - "dataset": "harddrive", - "index_pattern": "logs-tychon.harddrive-*", - "title": "Endpoint Harddrive Info" - }, - { - "dataset": "host", - "index_pattern": "logs-tychon.host-*", - "title": "Host Operating System Info" - }, - { - "dataset": "cve", - "index_pattern": "logs-tychon.cve-*", - "title": "Vulnerabilites" - }, - { - "dataset": "externaldevicecontrol", - "index_pattern": "logs-tychon.externaldevicecontrol-*", - "title": "Endpoint External Device Control" - }, - { - "dataset": "cmrs", - "index_pattern": "logs-tychon.cmrs-*", - "title": "DISA Continuous Monitoring and Risk Scoring Data" - }, - { - "dataset": "arp", - "index_pattern": "logs-tychon.arp-*", - "title": "Endpoint Arp Table Information" - }, - { - "dataset": "ciphers", - "index_pattern": "logs-tychon.ciphers-*", - "title": "Certificate Ciphers" - }, - { - "dataset": "features", - "index_pattern": "logs-tychon.features-*", - "title": "Features Info" - }, - { - "dataset": "epp", - "index_pattern": "logs-tychon.epp-*", - "title": "Endpoint Protection Platform Info" - }, - { - "dataset": "cpu", - "index_pattern": "logs-tychon.cpu-*", - "title": "Endpoint CPU Info" - }, - { - "dataset": "browser", - "index_pattern": "logs-tychon.browser-*", - "title": "Endpoint Browser Configurations" - }, - { - "dataset": "exposedservice", - "index_pattern": "logs-tychon.exposedservice-*", - "title": "Endpoint Exposed Services" - }, - { - "dataset": "volume", - "index_pattern": "logs-tychon.volume-*", - "title": "Endpoint Volumes Info" - }, - { - "dataset": "hardware", - "index_pattern": "logs-tychon.hardware-*", - "title": "Hardware Info" - }, - { - "dataset": "networkadapter", - "index_pattern": "logs-tychon.networkadapter-*", - "title": "Network Adapters" - } - ], - "elser_embedding": "TYCHON Agentless - Collect complete master endpoint datasets including vulnerability and STIG to comply with DISA endpoint requirements and C2C without adding services to your endpoints. - System Certificates Endpoint STIG Results Endpoint Software Inventory Info Endpoint Operational Attributes (Requires DATT) Endpoint Harddrive Info Host Operating System Info Vulnerabilites Endpoint External Device Control DISA Continuous Monitoring and Risk Scoring Data Endpoint Arp Table Information Certificate Ciphers Features Info Endpoint Protection Platform Info Endpoint CPU Info Endpoint Browser Configurations Endpoint Exposed Services Endpoint Volumes Info Hardware Info Network Adapters" - }, - { - "title": "Proofpoint On Demand", - "id": "proofpoint_on_demand", - "description": "Collect logs from Proofpoint On Demand with Elastic Agent.", - "data_streams": [ - { - "dataset": "message", - "index_pattern": "logs-proofpoint_on_demand.message-*", - "title": "Proofpoint On Demand Message logs" - }, - { - "dataset": "audit", - "index_pattern": "logs-proofpoint_on_demand.audit-*", - "title": "Proofpoint On Demand Audit logs" - }, - { - "dataset": "mail", - "index_pattern": "logs-proofpoint_on_demand.mail-*", - "title": "Proofpoint On Demand Mail logs" - } - ], - "elser_embedding": "Proofpoint On Demand - Collect logs from Proofpoint On Demand with Elastic Agent. - Proofpoint On Demand Message logs Proofpoint On Demand Audit logs Proofpoint On Demand Mail logs" - }, - { - "title": "Cisco ASA", - "id": "cisco_asa", - "description": "Collect logs from Cisco ASA with Elastic Agent.", - "data_streams": [ - { - "dataset": "log", - "index_pattern": "logs-cisco_asa.log-*", - "title": "Cisco ASA logs" - } - ], - "elser_embedding": "Cisco ASA - Collect logs from Cisco ASA with Elastic Agent. - Cisco ASA logs" - }, - { - "title": "Amazon Security Lake", - "id": "amazon_security_lake", - "description": "Collect logs from Amazon Security Lake with Elastic Agent.", - "data_streams": [ - { - "dataset": "network_activity", - "index_pattern": "logs-amazon_security_lake.network_activity-*", - "title": "Amazon Security Lake Network Activity Events" - }, - { - "dataset": "application_activity", - "index_pattern": "logs-amazon_security_lake.application_activity-*", - "title": "Amazon Security Lake Application Activity Events" - }, - { - "dataset": "discovery", - "index_pattern": "logs-amazon_security_lake.discovery-*", - "title": "Amazon Security Lake Discovery Events" - }, - { - "dataset": "findings", - "index_pattern": "logs-amazon_security_lake.findings-*", - "title": "Amazon Security Lake Findings Events" - }, - { - "dataset": "system_activity", - "index_pattern": "logs-amazon_security_lake.system_activity-*", - "title": "Amazon Security Lake System Activity Events" - }, - { - "dataset": "event", - "index_pattern": "logs-amazon_security_lake.event-*", - "title": "Collect Amazon Security Lake Events" - }, - { - "dataset": "iam", - "index_pattern": "logs-amazon_security_lake.iam-*", - "title": "Amazon Security Lake Identity and Access Management Events" - } - ], - "elser_embedding": "Amazon Security Lake - Collect logs from Amazon Security Lake with Elastic Agent. - Amazon Security Lake Network Activity Events Amazon Security Lake Application Activity Events Amazon Security Lake Discovery Events Amazon Security Lake Findings Events Amazon Security Lake System Activity Events Collect Amazon Security Lake Events Amazon Security Lake Identity and Access Management Events" - }, - { - "title": "Azure App Service", - "id": "azure_app_service", - "description": "Collect logs from Azure App Service with Elastic Agent.", - "data_streams": [ - { - "dataset": "app_service_logs", - "index_pattern": "logs-azure_app_service.app_service_logs-*", - "title": "Collect App Service logs from Azure" - } - ], - "elser_embedding": "Azure App Service - Collect logs from Azure App Service with Elastic Agent. - Collect App Service logs from Azure" - }, - { - "title": "ESET PROTECT", - "id": "eset_protect", - "description": "Collect logs from ESET PROTECT with Elastic Agent.", - "data_streams": [ - { - "dataset": "device_task", - "index_pattern": "logs-eset_protect.device_task-*", - "title": "Collect Device Task logs from ESET PROTECT" - }, - { - "dataset": "detection", - "index_pattern": "logs-eset_protect.detection-*", - "title": "Collect Detection logs from ESET PROTECT" - }, - { - "dataset": "event", - "index_pattern": "logs-eset_protect.event-*", - "title": "Collect Event logs from ESET PROTECT" - } - ], - "elser_embedding": "ESET PROTECT - Collect logs from ESET PROTECT with Elastic Agent. - Collect Device Task logs from ESET PROTECT Collect Detection logs from ESET PROTECT Collect Event logs from ESET PROTECT" - }, - { - "id": "endpoint", - "title": "Elastic Defend", - "description": "windows linux osx dns network process suspicious user registry host host-based endpoint analysis commandline cli command exfiltration ransomware detection system os operating traffic prevention file user modification integrity obfuscation powershell anomaly edr xdr", - "data_streams": [ - { - "dataset": "endpoint.events.api", - "title": "Endpoint API Events", - "index_pattern": "logs-endpoint.events.api-*" - }, - { - "dataset": "endpoint.events.file", - "title": "Endpoint File Events", - "index_pattern": "logs-endpoint.events.file-*" - }, - { - "dataset": "endpoint.events.library", - "title": "Endpoint Library and Driver Events", - "index_pattern": "logs-endpoint.events.library-*" - }, - { - "dataset": "endpoint.events.network", - "title": "Endpoint Network Events", - "index_pattern": "logs-endpoint.events.network-*" - }, - { - "dataset": "endpoint.events.process", - "title": "Endpoint Process Events", - "index_pattern": "logs-endpoint.events.process-*" - }, - { - "dataset": "endpoint.events.registry", - "title": "Endpoint Registry Events", - "index_pattern": "logs-endpoint.events.registry-*" - }, - { - "dataset": "endpoint.events.security", - "title": "Endpoint Security Events", - "index_pattern": "logs-endpoint.events.security-*" - } - ], - "elser_embedding": "Elastic Defend - windows linux osx dns network process suspicious user registry host host-based endpoint analysis commandline cli command exfiltration ransomware detection system os operating traffic prevention file user modification integrity obfuscation powershell anomaly edr xdr - Endpoint API Events Endpoint File Events Endpoint Library and Driver Events Endpoint Network Events Endpoint Process Events Endpoint Registry Events Endpoint Security Events" - } -] \ No newline at end of file diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_base_client.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_base_client.ts index e80e880545f68..974fe85dda5c1 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_base_client.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_base_client.ts @@ -18,7 +18,7 @@ import type { Logger, } from '@kbn/core/server'; import assert from 'assert'; -import type { Stored } from '../types'; +import type { Stored, SiemRuleMigrationsClientDependencies } from '../types'; import type { IndexNameProvider } from './rule_migrations_data_client'; const DEFAULT_PIT_KEEP_ALIVE: Duration = '30s' as const; @@ -30,7 +30,8 @@ export class RuleMigrationsDataBaseClient { protected getIndexName: IndexNameProvider, protected currentUser: AuthenticatedUser, protected esScopedClient: IScopedClusterClient, - protected logger: Logger + protected logger: Logger, + protected dependencies: SiemRuleMigrationsClientDependencies ) { this.esClient = esScopedClient.asInternalUser; } diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_client.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_client.ts index aec7a1931b502..a055c12c49123 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_client.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_client.ts @@ -6,12 +6,12 @@ */ import type { AuthenticatedUser, IScopedClusterClient, Logger } from '@kbn/core/server'; -import type { PackageService } from '@kbn/fleet-plugin/server'; import { RuleMigrationsDataIntegrationsClient } from './rule_migrations_data_integrations_client'; import { RuleMigrationsDataPrebuiltRulesClient } from './rule_migrations_data_prebuilt_rules_client'; import { RuleMigrationsDataResourcesClient } from './rule_migrations_data_resources_client'; import { RuleMigrationsDataRulesClient } from './rule_migrations_data_rules_client'; import { RuleMigrationsDataLookupsClient } from './rule_migrations_data_lookups_client'; +import type { SiemRuleMigrationsClientDependencies } from '../types'; import type { AdapterId } from './rule_migrations_data_service'; export type IndexNameProvider = () => Promise; @@ -29,32 +29,35 @@ export class RuleMigrationsDataClient { currentUser: AuthenticatedUser, esScopedClient: IScopedClusterClient, logger: Logger, - packageService?: PackageService + dependencies: SiemRuleMigrationsClientDependencies ) { this.rules = new RuleMigrationsDataRulesClient( indexNameProviders.rules, currentUser, esScopedClient, - logger + logger, + dependencies ); this.resources = new RuleMigrationsDataResourcesClient( indexNameProviders.resources, currentUser, esScopedClient, - logger + logger, + dependencies ); this.integrations = new RuleMigrationsDataIntegrationsClient( indexNameProviders.integrations, currentUser, esScopedClient, logger, - packageService + dependencies ); this.prebuiltRules = new RuleMigrationsDataPrebuiltRulesClient( indexNameProviders.prebuiltrules, currentUser, esScopedClient, - logger + logger, + dependencies ); this.lookups = new RuleMigrationsDataLookupsClient(currentUser, esScopedClient, logger); } diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_integrations_client.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_integrations_client.ts index 5df7cfe517f20..b9d5516d1d9d0 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_integrations_client.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_integrations_client.ts @@ -5,68 +5,70 @@ * 2.0. */ -import type { PackageService } from '@kbn/fleet-plugin/server'; -import type { AuthenticatedUser, IScopedClusterClient, Logger } from '@kbn/core/server'; import type { PackageList } from '@kbn/fleet-plugin/common'; import type { RuleMigrationIntegration } from '../types'; import { RuleMigrationsDataBaseClient } from './rule_migrations_data_base_client'; -/* This will be removed once the package registry changes is performed */ -import integrationsFile from './integrations_temp.json'; -import type { IndexNameProvider } from './rule_migrations_data_client'; - /* The minimum score required for a integration to be considered correct, might need to change this later */ const MIN_SCORE = 40 as const; /* The number of integrations the RAG will return, sorted by score */ const RETURNED_INTEGRATIONS = 5 as const; -/* This is a temp implementation to allow further development until https://github.com/elastic/package-registry/issues/1252 */ -const INTEGRATIONS = integrationsFile as RuleMigrationIntegration[]; /* BULK_MAX_SIZE defines the number to break down the bulk operations by. * The 500 number was chosen as a reasonable number to avoid large payloads. It can be adjusted if needed. */ export class RuleMigrationsDataIntegrationsClient extends RuleMigrationsDataBaseClient { - constructor( - getIndexName: IndexNameProvider, - currentUser: AuthenticatedUser, - esScopedClient: IScopedClusterClient, - logger: Logger, - private packageService?: PackageService - ) { - super(getIndexName, currentUser, esScopedClient, logger); - } - async getIntegrationPackages(): Promise { - return this.packageService?.asInternalUser.getPackages(); + return this.dependencies.packageService?.asInternalUser.getPackages(); } /** Indexes an array of integrations to be used with ELSER semantic search queries */ - async create(): Promise { + async populate(): Promise { const index = await this.getIndexName(); - await this.esClient - .bulk( - { - refresh: 'wait_for', - operations: INTEGRATIONS.flatMap((integration) => [ - { update: { _index: index, _id: integration.id } }, - { - doc: { - title: integration.title, - description: integration.description, - data_streams: integration.data_streams, - elser_embedding: integration.elser_embedding, - '@timestamp': new Date().toISOString(), + const packages = await this.dependencies.packageService?.asInternalUser.getPackages(); + if (packages) { + const ragIntegrations = packages.map((pkg) => ({ + title: pkg.title, + id: pkg.name, + description: pkg?.description || '', + data_streams: + pkg.data_streams?.map((stream) => ({ + dataset: stream.dataset, + index_pattern: `${stream.type}-${stream.dataset}-*`, + title: stream.title, + })) || [], + elser_embedding: [ + pkg.title, + pkg.description, + ...(pkg.data_streams?.map((stream) => stream.title) || []), + ].join(' - '), + })); + await this.esClient + .bulk( + { + refresh: 'wait_for', + operations: ragIntegrations.flatMap((integration) => [ + { update: { _index: index, _id: integration.id } }, + { + doc: { + title: integration.title, + description: integration.description, + data_streams: integration.data_streams, + elser_embedding: integration.elser_embedding, + }, + doc_as_upsert: true, }, - doc_as_upsert: true, - }, - ]), - }, - { requestTimeout: 10 * 60 * 1000 } - ) - .catch((error) => { - this.logger.error(`Error preparing integrations for SIEM migration ${error.message}`); - throw error; - }); + ]), + }, + { requestTimeout: 10 * 60 * 1000 } + ) + .catch((error) => { + this.logger.error(`Error populating integrations for migration ${error.message}`); + throw error; + }); + } else { + this.logger.warn('Package service not available, not able not populate integrations index'); + } } /** Based on a LLM generated semantic string, returns the 5 best results with a score above 40 */ diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_prebuilt_rules_client.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_prebuilt_rules_client.ts index ccc0b31b31dc3..30fe9a280ad14 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_prebuilt_rules_client.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_prebuilt_rules_client.ts @@ -5,19 +5,15 @@ * 2.0. */ -import type { RulesClient } from '@kbn/alerting-plugin/server'; -import type { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; +import type { RuleVersions } from '../../../detection_engine/prebuilt_rules/logic/diff/calculate_rule_diff'; import { createPrebuiltRuleAssetsClient } from '../../../detection_engine/prebuilt_rules/logic/rule_assets/prebuilt_rule_assets_client'; import { createPrebuiltRuleObjectsClient } from '../../../detection_engine/prebuilt_rules/logic/rule_objects/prebuilt_rule_objects_client'; import { fetchRuleVersionsTriad } from '../../../detection_engine/prebuilt_rules/logic/rule_versions/fetch_rule_versions_triad'; import type { RuleMigrationPrebuiltRule } from '../types'; import { RuleMigrationsDataBaseClient } from './rule_migrations_data_base_client'; -interface RetrievePrebuiltRulesParams { - soClient: SavedObjectsClientContract; - rulesClient: RulesClient; -} - +export type { RuleVersions }; +export type PrebuildRuleVersionsMap = Map; /* The minimum score required for a integration to be considered correct, might need to change this later */ const MIN_SCORE = 40 as const; /* The number of integrations the RAG will return, sorted by score */ @@ -29,17 +25,16 @@ const RETURNED_RULES = 5 as const; const BULK_MAX_SIZE = 500 as const; export class RuleMigrationsDataPrebuiltRulesClient extends RuleMigrationsDataBaseClient { - /** Indexes an array of integrations to be used with ELSER semantic search queries */ - async create({ soClient, rulesClient }: RetrievePrebuiltRulesParams): Promise { - const ruleAssetsClient = createPrebuiltRuleAssetsClient(soClient); - const ruleObjectsClient = createPrebuiltRuleObjectsClient(rulesClient); - - const ruleVersionsMap = await fetchRuleVersionsTriad({ - ruleAssetsClient, - ruleObjectsClient, - }); + async getRuleVersionsMap(): Promise { + const ruleAssetsClient = createPrebuiltRuleAssetsClient(this.dependencies.savedObjectsClient); + const ruleObjectsClient = createPrebuiltRuleObjectsClient(this.dependencies.rulesClient); + return fetchRuleVersionsTriad({ ruleAssetsClient, ruleObjectsClient }); + } + /** Indexes an array of integrations to be used with ELSER semantic search queries */ + async populate(ruleVersionsMap: PrebuildRuleVersionsMap): Promise { const filteredRules: RuleMigrationPrebuiltRule[] = []; + ruleVersionsMap.forEach((ruleVersions) => { const rule = ruleVersions.target || ruleVersions.current; if (rule) { @@ -50,7 +45,6 @@ export class RuleMigrationsDataPrebuiltRulesClient extends RuleMigrationsDataBas filteredRules.push({ rule_id: rule.rule_id, name: rule.name, - installed_rule_id: ruleVersions.current?.id, description: rule.description, elser_embedding: `${rule.name} - ${rule.description}`, ...(mitreAttackIds?.length && { mitre_attack_ids: mitreAttackIds }), @@ -87,10 +81,7 @@ export class RuleMigrationsDataPrebuiltRulesClient extends RuleMigrationsDataBas } /** Based on a LLM generated semantic string, returns the 5 best results with a score above 40 */ - async retrieveRules( - semanticString: string, - techniqueIds: string - ): Promise { + async search(semanticString: string, techniqueIds: string): Promise { const index = await this.getIndexName(); const query = { bool: { @@ -126,7 +117,7 @@ export class RuleMigrationsDataPrebuiltRulesClient extends RuleMigrationsDataBas size: RETURNED_RULES, min_score: MIN_SCORE, }) - .then(this.processResponseHits.bind(this)) + .then((response) => this.processResponseHits(response)) .catch((error) => { this.logger.error(`Error querying prebuilt rule details for ELSER: ${error.message}`); throw error; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_rules_client.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_rules_client.ts index 85a78cf14b849..d66b1f54a710c 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_rules_client.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_rules_client.ts @@ -15,6 +15,7 @@ import type { QueryDslQueryContainer, Duration, } from '@elastic/elasticsearch/lib/api/types'; +import type { RuleMigrationFilters } from '../../../../../common/siem_migrations/types'; import type { InternalUpdateRuleMigrationData, StoredRuleMigration } from '../types'; import { SiemMigrationStatus, @@ -36,18 +37,6 @@ export type CreateRuleMigrationInput = Omit< export type RuleMigrationDataStats = Omit; export type RuleMigrationAllDataStats = RuleMigrationDataStats[]; -export interface RuleMigrationFilters { - status?: SiemMigrationStatus | SiemMigrationStatus[]; - ids?: string[]; - installed?: boolean; - installable?: boolean; - prebuilt?: boolean; - failed?: boolean; - fullyTranslated?: boolean; - partiallyTranslated?: boolean; - untranslatable?: boolean; - searchTerm?: string; -} export interface RuleMigrationGetOptions { filters?: RuleMigrationFilters; sort?: RuleMigrationSort; @@ -397,66 +386,55 @@ export class RuleMigrationsDataRulesClient extends RuleMigrationsDataBaseClient private getFilterQuery( migrationId: string, - { - status, - ids, - installed, - installable, - prebuilt, - searchTerm, - failed, - fullyTranslated, - partiallyTranslated, - untranslatable, - }: RuleMigrationFilters = {} + filters: RuleMigrationFilters = {} ): QueryDslQueryContainer { const filter: QueryDslQueryContainer[] = [{ term: { migration_id: migrationId } }]; - if (status) { - if (Array.isArray(status)) { - filter.push({ terms: { status } }); + if (filters.status) { + if (Array.isArray(filters.status)) { + filter.push({ terms: { status: filters.status } }); } else { - filter.push({ term: { status } }); + filter.push({ term: { status: filters.status } }); } } - if (ids) { - filter.push({ terms: { _id: ids } }); + if (filters.ids) { + filter.push({ terms: { _id: filters.ids } }); } - if (searchTerm?.length) { - filter.push(searchConditions.matchTitle(searchTerm)); + if (filters.searchTerm?.length) { + filter.push(searchConditions.matchTitle(filters.searchTerm)); } - if (installed === true) { + if (filters.installed === true) { filter.push(searchConditions.isInstalled()); - } else if (installed === false) { + } else if (filters.installed === false) { filter.push(searchConditions.isNotInstalled()); } - if (installable === true) { + if (filters.installable === true) { filter.push(...searchConditions.isInstallable()); - } else if (installable === false) { + } else if (filters.installable === false) { filter.push(...searchConditions.isNotInstallable()); } - if (prebuilt === true) { + if (filters.prebuilt === true) { filter.push(searchConditions.isPrebuilt()); - } else if (prebuilt === false) { + } else if (filters.prebuilt === false) { filter.push(searchConditions.isCustom()); } - if (failed === true) { + if (filters.failed === true) { filter.push(searchConditions.isFailed()); - } else if (failed === false) { + } else if (filters.failed === false) { filter.push(searchConditions.isNotFailed()); } - if (fullyTranslated === true) { + if (filters.fullyTranslated === true) { filter.push(searchConditions.isFullyTranslated()); - } else if (fullyTranslated === false) { + } else if (filters.fullyTranslated === false) { filter.push(searchConditions.isNotFullyTranslated()); } - if (partiallyTranslated === true) { + if (filters.partiallyTranslated === true) { filter.push(searchConditions.isPartiallyTranslated()); - } else if (partiallyTranslated === false) { + } else if (filters.partiallyTranslated === false) { filter.push(searchConditions.isNotPartiallyTranslated()); } - if (untranslatable === true) { + if (filters.untranslatable === true) { filter.push(searchConditions.isUntranslatable()); - } else if (untranslatable === false) { + } else if (filters.untranslatable === false) { filter.push(searchConditions.isNotUntranslatable()); } return { bool: { filter } }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_service.test.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_service.test.ts index cb6c94ebae40f..626790104a454 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_service.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_service.test.ts @@ -12,6 +12,7 @@ import type { InstallParams } from '@kbn/index-adapter'; import { IndexPatternAdapter, IndexAdapter } from '@kbn/index-adapter'; import { loggerMock } from '@kbn/logging-mocks'; import { Subject } from 'rxjs'; +import type { SiemRuleMigrationsClientDependencies } from '../types'; import type { IndexNameProviders } from './rule_migrations_data_client'; import { INDEX_PATTERN, RuleMigrationsDataService } from './rule_migrations_data_service'; @@ -30,6 +31,7 @@ const MockedIndexPatternAdapter = IndexPatternAdapter as unknown as jest.MockedC >; const MockedIndexAdapter = IndexAdapter as unknown as jest.MockedClass; +const dependencies = {} as SiemRuleMigrationsClientDependencies; const esClient = elasticsearchServiceMock.createStart().client.asInternalUser; describe('SiemRuleMigrationsDataService', () => { @@ -106,6 +108,7 @@ describe('SiemRuleMigrationsDataService', () => { spaceId: 'space1', currentUser, esScopedClient: elasticsearchServiceMock.createStart().client.asScoped(), + dependencies, }; it('should install space index pattern', async () => { diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_service.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_service.ts index 094e48ab90771..c0254b90313fe 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_service.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_service.ts @@ -11,9 +11,9 @@ import { type FieldMap, type InstallParams, } from '@kbn/index-adapter'; -import type { PackageService } from '@kbn/fleet-plugin/server'; import type { IndexNameProvider, IndexNameProviders } from './rule_migrations_data_client'; import { RuleMigrationsDataClient } from './rule_migrations_data_client'; +import type { SiemRuleMigrationsClientDependencies } from '../types'; import { integrationsFieldMap, prebuiltRulesFieldMap, @@ -37,7 +37,7 @@ interface CreateClientParams { spaceId: string; currentUser: AuthenticatedUser; esScopedClient: IScopedClusterClient; - packageService?: PackageService; + dependencies: SiemRuleMigrationsClientDependencies; } interface CreateAdapterParams { adapterId: AdapterId; @@ -103,12 +103,7 @@ export class RuleMigrationsDataService { ]); } - public createClient({ - spaceId, - currentUser, - esScopedClient, - packageService, - }: CreateClientParams) { + public createClient({ spaceId, currentUser, esScopedClient, dependencies }: CreateClientParams) { const indexNameProviders: IndexNameProviders = { rules: this.createIndexNameProvider(this.adapters.rules, spaceId), resources: this.createIndexNameProvider(this.adapters.resources, spaceId), @@ -121,7 +116,7 @@ export class RuleMigrationsDataService { currentUser, esScopedClient, this.logger, - packageService + dependencies ); } diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_field_maps.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_field_maps.ts index 9369b3b5e1bc7..0ea2913d3ebd6 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_field_maps.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_field_maps.ts @@ -17,21 +17,22 @@ export const ruleMigrationsFieldMap: FieldMap [ + ...sortingOptions.severity(direction), + ...sortingOptions.riskScore(direction), + ...sortingOptions.status('desc'), + ...sortingOptions.matchedPrebuiltRule('desc'), + ], + 'elastic_rule.risk_score': (direction?: estypes.SortOrder) => [ + ...sortingOptions.riskScore(direction), ...sortingOptions.severity(direction), ...sortingOptions.status('desc'), ...sortingOptions.matchedPrebuiltRule('desc'), @@ -122,11 +128,13 @@ const sortingOptionsMap: { ...sortingOptions.matchedPrebuiltRule(direction), ...sortingOptions.status('desc'), ...sortingOptions.severity('desc'), + ...sortingOptions.riskScore(direction), ], translation_result: (direction?: estypes.SortOrder) => [ ...sortingOptions.status(direction), ...sortingOptions.matchedPrebuiltRule('desc'), ...sortingOptions.severity('desc'), + ...sortingOptions.riskScore(direction), ], updated_at: sortingOptions.updated, }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/siem_rule_migrations_service.test.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/siem_rule_migrations_service.test.ts index a25fa7d576114..e11b781bb445c 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/siem_rule_migrations_service.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/siem_rule_migrations_service.test.ts @@ -22,10 +22,13 @@ import { } from './data/__mocks__/mocks'; import { mockCreateClient as mockTaskCreateClient, mockStopAll } from './task/__mocks__/mocks'; import { waitFor } from '@testing-library/dom'; +import type { SiemRuleMigrationsClientDependencies } from './types'; jest.mock('./data/rule_migrations_data_service'); jest.mock('./task/rule_migrations_task_service'); +const dependencies = {} as SiemRuleMigrationsClientDependencies; + describe('SiemRuleMigrationsService', () => { let ruleMigrationsService: SiemRuleMigrationsService; const kibanaVersion = '8.16.0'; @@ -74,6 +77,7 @@ describe('SiemRuleMigrationsService', () => { spaceId: 'default', currentUser, request: httpServerMock.createKibanaRequest(), + dependencies, }; }); @@ -96,6 +100,7 @@ describe('SiemRuleMigrationsService', () => { spaceId: createClientParams.spaceId, currentUser: createClientParams.currentUser, esScopedClient: esClusterClient.asScoped(), + dependencies, }); }); @@ -104,6 +109,7 @@ describe('SiemRuleMigrationsService', () => { expect(mockTaskCreateClient).toHaveBeenCalledWith({ currentUser: createClientParams.currentUser, dataClient: mockDataCreateClient(), + dependencies, }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/siem_rule_migrations_service.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/siem_rule_migrations_service.ts index e3c6d4a13b15b..70a834872d85f 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/siem_rule_migrations_service.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/siem_rule_migrations_service.ts @@ -14,11 +14,11 @@ import type { KibanaRequest, Logger, } from '@kbn/core/server'; -import type { PackageService } from '@kbn/fleet-plugin/server'; import { RuleMigrationsDataService } from './data/rule_migrations_data_service'; import type { RuleMigrationsDataClient } from './data/rule_migrations_data_client'; import type { RuleMigrationsTaskClient } from './task/rule_migrations_task_client'; import { RuleMigrationsTaskService } from './task/rule_migrations_task_service'; +import type { SiemRuleMigrationsClientDependencies } from './types'; export interface SiemRulesMigrationsSetupParams { esClusterClient: IClusterClient; @@ -30,7 +30,7 @@ export interface SiemRuleMigrationsCreateClientParams { request: KibanaRequest; currentUser: AuthenticatedUser | null; spaceId: string; - packageService?: PackageService; + dependencies: SiemRuleMigrationsClientDependencies; } export interface SiemRuleMigrationsClient { @@ -60,10 +60,10 @@ export class SiemRuleMigrationsService { } createClient({ - spaceId, - currentUser, - packageService, request, + currentUser, + spaceId, + dependencies, }: SiemRuleMigrationsCreateClientParams): SiemRuleMigrationsClient { assert(currentUser, 'Current user must be authenticated'); assert(this.esClusterClient, 'ES client not available, please call setup first'); @@ -73,9 +73,9 @@ export class SiemRuleMigrationsService { spaceId, currentUser, esScopedClient, - packageService, + dependencies, }); - const taskClient = this.taskService.createClient({ currentUser, dataClient }); + const taskClient = this.taskService.createClient({ currentUser, dataClient, dependencies }); return { data: dataClient, task: taskClient }; } diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/agent/nodes/match_prebuilt_rule/match_prebuilt_rule.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/agent/nodes/match_prebuilt_rule/match_prebuilt_rule.ts index fd3dfc983443e..804e7a8bc3953 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/agent/nodes/match_prebuilt_rule/match_prebuilt_rule.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/agent/nodes/match_prebuilt_rule/match_prebuilt_rule.ts @@ -7,7 +7,11 @@ import type { Logger } from '@kbn/core/server'; import { JsonOutputParser } from '@langchain/core/output_parsers'; -import { RuleTranslationResult } from '../../../../../../../../common/siem_migrations/constants'; +import { + DEFAULT_TRANSLATION_RISK_SCORE, + DEFAULT_TRANSLATION_SEVERITY, + RuleTranslationResult, +} from '../../../../../../../../common/siem_migrations/constants'; import type { RuleMigrationsRetriever } from '../../../retrievers'; import type { ChatModel } from '../../../util/actions_client_chat'; import type { GraphNode } from '../../types'; @@ -33,7 +37,7 @@ export const getMatchPrebuiltRuleNode = ({ return async (state) => { const query = state.semantic_query; const techniqueIds = state.original_rule.annotations?.mitre_attack || []; - const prebuiltRules = await ruleMigrationsRetriever.prebuiltRules.getRules( + const prebuiltRules = await ruleMigrationsRetriever.prebuiltRules.search( query, techniqueIds.join(',') ); @@ -74,8 +78,11 @@ export const getMatchPrebuiltRuleNode = ({ elastic_rule: { title: matchedRule.name, description: matchedRule.description, - id: matchedRule.installed_rule_id, prebuilt_rule_id: matchedRule.rule_id, + id: matchedRule.current?.id, + integration_ids: matchedRule.target?.related_integrations?.map((i) => i.package), + severity: matchedRule.target?.severity ?? DEFAULT_TRANSLATION_SEVERITY, + risk_score: matchedRule.target?.risk_score ?? DEFAULT_TRANSLATION_RISK_SCORE, }, translation_result: RuleTranslationResult.FULL, }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/agent/sub_graphs/translate_rule/nodes/translate_rule/translate_rule.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/agent/sub_graphs/translate_rule/nodes/translate_rule/translate_rule.ts index d360b6a1c246d..e12d3e3da13b8 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/agent/sub_graphs/translate_rule/nodes/translate_rule/translate_rule.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/agent/sub_graphs/translate_rule/nodes/translate_rule/translate_rule.ts @@ -49,7 +49,7 @@ export const getTranslateRuleNode = ({ response, comments: [cleanMarkdown(translationSummary)], elastic_rule: { - integration_id: integrationId, + integration_ids: [integrationId], query: esqlQuery, query_language: 'esql', }, diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/agent/sub_graphs/translate_rule/nodes/translation_result/translation_result.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/agent/sub_graphs/translate_rule/nodes/translation_result/translation_result.ts index c70b4d3445ec7..30083abdf2909 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/agent/sub_graphs/translate_rule/nodes/translation_result/translation_result.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/agent/sub_graphs/translate_rule/nodes/translation_result/translation_result.ts @@ -5,7 +5,11 @@ * 2.0. */ -import { RuleTranslationResult } from '../../../../../../../../../../common/siem_migrations/constants'; +import { + DEFAULT_TRANSLATION_RISK_SCORE, + DEFAULT_TRANSLATION_SEVERITY, + RuleTranslationResult, +} from '../../../../../../../../../../common/siem_migrations/constants'; import type { GraphNode } from '../../types'; export const translationResultNode: GraphNode = async (state) => { @@ -13,7 +17,8 @@ export const translationResultNode: GraphNode = async (state) => { const elasticRule = { title: state.original_rule.title, description: state.original_rule.description || state.original_rule.title, - severity: 'low', + severity: DEFAULT_TRANSLATION_SEVERITY, + risk_score: DEFAULT_TRANSLATION_RISK_SCORE, ...state.elastic_rule, }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/retrievers/integration_retriever.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/retrievers/integration_retriever.ts index 18ddb51a5b83b..b79e0cc3d9070 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/retrievers/integration_retriever.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/retrievers/integration_retriever.ts @@ -12,8 +12,7 @@ export class IntegrationRetriever { constructor(private readonly clients: RuleMigrationsRetrieverClients) {} public async populateIndex() { - // TODO: use Fleet API client for integration retrieval as an argument once feature is available - return this.clients.data.integrations.create(); + return this.clients.data.integrations.populate(); } public async getIntegrations(semanticString: string): Promise { diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/retrievers/prebuilt_rules_retriever.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/retrievers/prebuilt_rules_retriever.ts index 03fd24d4e6b4d..cbce72b5ff88c 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/retrievers/prebuilt_rules_retriever.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/retrievers/prebuilt_rules_retriever.ts @@ -5,27 +5,33 @@ * 2.0. */ -import type { RuleMigrationPrebuiltRule } from '../../types'; +import type { PrebuildRuleVersionsMap } from '../../data/rule_migrations_data_prebuilt_rules_client'; +import type { RuleSemanticSearchResult } from '../../types'; import type { RuleMigrationsRetrieverClients } from './rule_migrations_retriever'; export class PrebuiltRulesRetriever { - constructor(private readonly clients: RuleMigrationsRetrieverClients) {} + private rulesMap?: PrebuildRuleVersionsMap; - // TODO: - // 1. Implement the `initialize` method to retrieve prebuilt rules and keep them in memory. - // 2. Improve the `retrieveRules` method to return the real prebuilt rules instead of the ELSER index doc. + constructor(private readonly clients: RuleMigrationsRetrieverClients) {} public async populateIndex() { - return this.clients.data.prebuiltRules.create({ - rulesClient: this.clients.rules, - soClient: this.clients.savedObjects, - }); + if (!this.rulesMap) { + this.rulesMap = await this.clients.data.prebuiltRules.getRuleVersionsMap(); + } + return this.clients.data.prebuiltRules.populate(this.rulesMap); } - public async getRules( + public async search( semanticString: string, techniqueIds: string - ): Promise { - return this.clients.data.prebuiltRules.retrieveRules(semanticString, techniqueIds); + ): Promise { + if (!this.rulesMap) { + this.rulesMap = await this.clients.data.prebuiltRules.getRuleVersionsMap(); + } + const results = await this.clients.data.prebuiltRules.search(semanticString, techniqueIds); + return results.map((rule) => { + const versions = this.rulesMap?.get(rule.rule_id) ?? {}; + return { ...rule, ...versions }; + }); } } diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/rule_migrations_task_client.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/rule_migrations_task_client.ts index b68ce9e2a6828..83f41d503bfa9 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/rule_migrations_task_client.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/rule_migrations_task_client.ts @@ -13,18 +13,17 @@ import { SiemMigrationTaskStatus, } from '../../../../../common/siem_migrations/constants'; import type { RuleMigrationTaskStats } from '../../../../../common/siem_migrations/model/rule_migration.gen'; +import type { RuleMigrationFilters } from '../../../../../common/siem_migrations/types'; import type { RuleMigrationsDataClient } from '../data/rule_migrations_data_client'; -import type { - RuleMigrationDataStats, - RuleMigrationFilters, -} from '../data/rule_migrations_data_rules_client'; +import type { RuleMigrationDataStats } from '../data/rule_migrations_data_rules_client'; +import type { SiemRuleMigrationsClientDependencies } from '../types'; import { getRuleMigrationAgent } from './agent'; import type { MigrateRuleState } from './agent/types'; import { RuleMigrationsRetriever } from './retrievers'; import type { MigrationAgent, - RuleMigrationTaskStartParams, RuleMigrationTaskCreateAgentParams, + RuleMigrationTaskStartParams, RuleMigrationTaskStartResult, RuleMigrationTaskStopResult, } from './types'; @@ -40,7 +39,8 @@ export class RuleMigrationsTaskClient { private migrationsRunning: MigrationsRunning, private logger: Logger, private data: RuleMigrationsDataClient, - private currentUser: AuthenticatedUser + private currentUser: AuthenticatedUser, + private dependencies: SiemRuleMigrationsClientDependencies ) {} /** Starts a rule migration task */ @@ -169,7 +169,7 @@ export class RuleMigrationsTaskClient { this.logger.info(`Abort signal received, stopping migration ID:${migrationId}`); return; } else { - this.logger.error(`Error processing migration ID:${migrationId}`, error); + this.logger.error(`Error processing migration ID:${migrationId} ${error}`); } } finally { this.migrationsRunning.delete(migrationId); @@ -180,12 +180,10 @@ export class RuleMigrationsTaskClient { private async createAgent({ migrationId, connectorId, - inferenceClient, - actionsClient, - rulesClient, - soClient, abortController, }: RuleMigrationTaskCreateAgentParams): Promise { + const { inferenceClient, actionsClient, rulesClient, savedObjectsClient } = this.dependencies; + const actionsClientChat = new ActionsClientChat(connectorId, actionsClient, this.logger); const model = await actionsClientChat.createModel({ signal: abortController.signal, @@ -195,7 +193,7 @@ export class RuleMigrationsTaskClient { const ruleMigrationsRetriever = new RuleMigrationsRetriever(migrationId, { data: this.data, rules: rulesClient, - savedObjects: soClient, + savedObjects: savedObjectsClient, }); await ruleMigrationsRetriever.initialize(); diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/rule_migrations_task_service.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/rule_migrations_task_service.ts index 89147f296b321..9b8d9f86245d5 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/rule_migrations_task_service.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/rule_migrations_task_service.ts @@ -21,12 +21,14 @@ export class RuleMigrationsTaskService { public createClient({ currentUser, dataClient, + dependencies, }: RuleMigrationTaskCreateClientParams): RuleMigrationsTaskClient { return new RuleMigrationsTaskClient( this.migrationsRunning, this.logger, dataClient, - currentUser + currentUser, + dependencies ); } diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/types.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/types.ts index 7ddb08f1e47d6..59c41212c9ced 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/types.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/task/types.ts @@ -5,12 +5,10 @@ * 2.0. */ -import type { AuthenticatedUser, SavedObjectsClientContract } from '@kbn/core/server'; +import type { AuthenticatedUser } from '@kbn/core/server'; import type { RunnableConfig } from '@langchain/core/runnables'; -import type { InferenceClient } from '@kbn/inference-plugin/server'; -import type { ActionsClient } from '@kbn/actions-plugin/server'; -import type { RulesClient } from '@kbn/alerting-plugin/server'; import type { RuleMigrationsDataClient } from '../data/rule_migrations_data_client'; +import type { SiemRuleMigrationsClientDependencies } from '../types'; import type { getRuleMigrationAgent } from './agent'; export type MigrationAgent = ReturnType; @@ -18,16 +16,13 @@ export type MigrationAgent = ReturnType; export interface RuleMigrationTaskCreateClientParams { currentUser: AuthenticatedUser; dataClient: RuleMigrationsDataClient; + dependencies: SiemRuleMigrationsClientDependencies; } export interface RuleMigrationTaskStartParams { migrationId: string; connectorId: string; invocationConfig: RunnableConfig; - inferenceClient: InferenceClient; - actionsClient: ActionsClient; - rulesClient: RulesClient; - soClient: SavedObjectsClientContract; } export interface RuleMigrationTaskCreateAgentParams extends RuleMigrationTaskStartParams { diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/types.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/types.ts index 03811c506be35..63abc6d856407 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/types.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/types.ts @@ -5,6 +5,11 @@ * 2.0. */ +import type { SavedObjectsClientContract } from '@kbn/core/server'; +import type { PackageService } from '@kbn/fleet-plugin/server'; +import type { RulesClient } from '@kbn/alerting-plugin/server'; +import type { ActionsClient } from '@kbn/actions-plugin/server'; +import type { InferenceClient } from '@kbn/inference-plugin/server'; import type { UpdateRuleMigrationData, RuleMigrationTranslationResult, @@ -13,12 +18,21 @@ import { type RuleMigration, type RuleMigrationResource, } from '../../../../common/siem_migrations/model/rule_migration.gen'; +import type { RuleVersions } from './data/rule_migrations_data_prebuilt_rules_client'; export type Stored = T & { id: string }; export type StoredRuleMigration = Stored; export type StoredRuleMigrationResource = Stored; +export interface SiemRuleMigrationsClientDependencies { + inferenceClient: InferenceClient; + rulesClient: RulesClient; + actionsClient: ActionsClient; + savedObjectsClient: SavedObjectsClientContract; + packageService?: PackageService; +} + export interface RuleMigrationIntegration { id: string; title: string; @@ -29,13 +43,14 @@ export interface RuleMigrationIntegration { export interface RuleMigrationPrebuiltRule { rule_id: string; - installed_rule_id?: string; name: string; description: string; elser_embedding: string; mitre_attack_ids?: string[]; } +export type RuleSemanticSearchResult = RuleMigrationPrebuiltRule & RuleVersions; + export type InternalUpdateRuleMigrationData = UpdateRuleMigrationData & { translation_result?: RuleMigrationTranslationResult; }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/siem_migrations_service.test.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/siem_migrations_service.test.ts index adf77756cce34..cb521a06285e8 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/siem_migrations_service.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/siem_migrations_service.test.ts @@ -18,6 +18,7 @@ import { mockStop, } from './rules/__mocks__/mocks'; import type { ConfigType } from '../../config'; +import type { SiemRuleMigrationsClientDependencies } from './rules/types'; jest.mock('./rules/siem_rule_migrations_service'); @@ -27,6 +28,8 @@ jest.mock('rxjs', () => ({ ReplaySubject: jest.fn().mockImplementation(() => mockReplaySubject$), })); +const dependencies = {} as SiemRuleMigrationsClientDependencies; + describe('SiemMigrationsService', () => { let siemMigrationsService: SiemMigrationsService; const kibanaVersion = '8.16.0'; @@ -70,6 +73,7 @@ describe('SiemMigrationsService', () => { spaceId: 'default', request: httpServerMock.createKibanaRequest(), currentUser, + dependencies, }; siemMigrationsService.createRulesClient(createRulesClientParams); expect(mockCreateClient).toHaveBeenCalledWith(createRulesClientParams); diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/telemetry/sender.test.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/telemetry/sender.test.ts index 882840f17674f..648bb8358e1d2 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/telemetry/sender.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/telemetry/sender.test.ts @@ -9,6 +9,7 @@ import { TelemetryEventsSender } from './sender'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; +import { Observable } from 'rxjs'; import { URL } from 'url'; describe('TelemetryEventsSender', () => { @@ -483,6 +484,7 @@ describe('TelemetryEventsSender', () => { const sender = new TelemetryEventsSender(logger); sender['telemetryStart'] = { getIsOptedIn: jest.fn(async () => true), + isOptedIn$: new Observable(), }; sender['telemetrySetup'] = { getTelemetryUrl: jest.fn(async () => new URL('https://telemetry.elastic.co')), @@ -516,6 +518,7 @@ describe('TelemetryEventsSender', () => { sender['sendEvents'] = jest.fn(); const telemetryStart = { getIsOptedIn: jest.fn(async () => false), + isOptedIn$: new Observable(), }; sender['telemetryStart'] = telemetryStart; @@ -532,6 +535,7 @@ describe('TelemetryEventsSender', () => { sender['sendEvents'] = jest.fn(); const telemetryStart = { getIsOptedIn: jest.fn(async () => true), + isOptedIn$: new Observable(), }; sender['telemetryStart'] = telemetryStart; sender['isTelemetryServicesReachable'] = jest.fn(async () => false); diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/draft_timelines/clean_draft_timelines/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/draft_timelines/clean_draft_timelines/index.ts index 639a5a2ae0e8c..29b587cc5bae0 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/draft_timelines/clean_draft_timelines/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/draft_timelines/clean_draft_timelines/index.ts @@ -33,7 +33,7 @@ export const cleanDraftTimelinesRoute = (router: SecuritySolutionPluginRouter) = path: TIMELINE_DRAFT_URL, security: { authz: { - requiredPrivileges: ['securitySolution'], + requiredPrivileges: ['timeline_write'], }, }, access: 'public', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/draft_timelines/get_draft_timelines/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/draft_timelines/get_draft_timelines/index.ts index 37db10f5393bc..bee539d2893d8 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/draft_timelines/get_draft_timelines/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/draft_timelines/get_draft_timelines/index.ts @@ -26,7 +26,7 @@ export const getDraftTimelinesRoute = (router: SecuritySolutionPluginRouter) => path: TIMELINE_DRAFT_URL, security: { authz: { - requiredPrivileges: ['securitySolution'], + requiredPrivileges: ['timeline_read'], }, }, access: 'public', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/notes/delete_note.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/notes/delete_note.ts index c2bc36e18c357..620972f9cc31b 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/notes/delete_note.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/notes/delete_note.ts @@ -24,7 +24,7 @@ export const deleteNoteRoute = (router: SecuritySolutionPluginRouter) => { path: NOTE_URL, security: { authz: { - requiredPrivileges: ['securitySolution'], + requiredPrivileges: ['notes_write'], }, }, access: 'public', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/notes/get_notes.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/notes/get_notes.ts index 49075a1b91155..a5110c8dc73b8 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/notes/get_notes.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/notes/get_notes.ts @@ -39,7 +39,7 @@ export const getNotesRoute = ( path: NOTE_URL, security: { authz: { - requiredPrivileges: ['securitySolution'], + requiredPrivileges: ['notes_read'], }, }, access: 'public', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/notes/persist_note.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/notes/persist_note.ts index 12fed18a5c396..939952f685783 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/notes/persist_note.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/notes/persist_note.ts @@ -27,7 +27,7 @@ export const persistNoteRoute = (router: SecuritySolutionPluginRouter) => { path: NOTE_URL, security: { authz: { - requiredPrivileges: ['securitySolution'], + requiredPrivileges: ['notes_write'], }, }, access: 'public', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/pinned_events/persist_pinned_event.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/pinned_events/persist_pinned_event.ts index 7dd66f86245ab..7a2adb7b94db7 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/pinned_events/persist_pinned_event.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/pinned_events/persist_pinned_event.ts @@ -28,7 +28,7 @@ export const persistPinnedEventRoute = (router: SecuritySolutionPluginRouter) => path: PINNED_EVENT_URL, security: { authz: { - requiredPrivileges: ['securitySolution'], + requiredPrivileges: ['timeline_write'], }, }, access: 'public', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/prepackaged_timelines/install_prepackaged_timelines/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/prepackaged_timelines/install_prepackaged_timelines/index.ts index 99c4d95942f15..af1fefa80309c 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/prepackaged_timelines/install_prepackaged_timelines/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/prepackaged_timelines/install_prepackaged_timelines/index.ts @@ -36,7 +36,7 @@ export const installPrepackedTimelinesRoute = ( path: `${TIMELINE_PREPACKAGED_URL}`, security: { authz: { - requiredPrivileges: ['securitySolution'], + requiredPrivileges: ['timeline_write'], }, }, options: { diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/copy_timeline/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/copy_timeline/index.ts index 2241de72b3307..736eb00a6b1bf 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/copy_timeline/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/copy_timeline/index.ts @@ -25,7 +25,7 @@ export const copyTimelineRoute = (router: SecuritySolutionPluginRouter) => { path: TIMELINE_COPY_URL, security: { authz: { - requiredPrivileges: ['securitySolution'], + requiredPrivileges: ['timeline_write'], }, }, access: 'internal', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/create_timelines/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/create_timelines/index.ts index e6af5abd78425..bd11a7571b048 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/create_timelines/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/create_timelines/index.ts @@ -34,7 +34,7 @@ export const createTimelinesRoute = (router: SecuritySolutionPluginRouter) => { path: TIMELINE_URL, security: { authz: { - requiredPrivileges: ['securitySolution'], + requiredPrivileges: ['timeline_write'], }, }, access: 'public', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/export_timelines/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/export_timelines/index.ts index 5a055d54a76ce..351a9015a636a 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/export_timelines/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/export_timelines/index.ts @@ -28,7 +28,7 @@ export const exportTimelinesRoute = (router: SecuritySolutionPluginRouter, confi path: TIMELINE_EXPORT_URL, security: { authz: { - requiredPrivileges: ['securitySolution'], + requiredPrivileges: ['timeline_read'], }, }, access: 'public', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/get_timeline/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/get_timeline/index.ts index 75d61987e775b..3849e7411dcd0 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/get_timeline/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/get_timeline/index.ts @@ -27,7 +27,7 @@ export const getTimelineRoute = (router: SecuritySolutionPluginRouter) => { path: TIMELINE_URL, security: { authz: { - requiredPrivileges: ['securitySolution'], + requiredPrivileges: ['timeline_read'], }, }, access: 'public', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/get_timelines/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/get_timelines/index.ts index 2ebcb4c38c37e..77f4937f13f8d 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/get_timelines/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/get_timelines/index.ts @@ -27,7 +27,7 @@ export const getTimelinesRoute = (router: SecuritySolutionPluginRouter) => { path: TIMELINES_URL, security: { authz: { - requiredPrivileges: ['securitySolution'], + requiredPrivileges: ['timeline_read'], }, }, access: 'public', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/import_timelines/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/import_timelines/index.ts index 3e40a7a7ebcb0..b424c1e9a60ab 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/import_timelines/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/import_timelines/index.ts @@ -34,7 +34,7 @@ export const importTimelinesRoute = (router: SecuritySolutionPluginRouter, confi path: `${TIMELINE_IMPORT_URL}`, security: { authz: { - requiredPrivileges: ['securitySolution'], + requiredPrivileges: ['timeline_write'], }, }, options: { diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/patch_timelines/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/patch_timelines/index.ts index 340b8611901e5..cec181212f461 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/patch_timelines/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/patch_timelines/index.ts @@ -28,7 +28,7 @@ export const patchTimelinesRoute = (router: SecuritySolutionPluginRouter) => { path: TIMELINE_URL, security: { authz: { - requiredPrivileges: ['securitySolution'], + requiredPrivileges: ['timeline_write'], }, }, access: 'public', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/persist_favorite/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/persist_favorite/index.ts index ed3531d8bd744..31d80eebcf9aa 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/persist_favorite/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/persist_favorite/index.ts @@ -28,7 +28,7 @@ export const persistFavoriteRoute = (router: SecuritySolutionPluginRouter) => { path: TIMELINE_FAVORITE_URL, security: { authz: { - requiredPrivileges: ['securitySolution'], + requiredPrivileges: ['timeline_read'], }, }, access: 'public', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/resolve_timeline/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/resolve_timeline/index.ts index 8e6ff9e8adca7..26369b34c63f5 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/resolve_timeline/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/resolve_timeline/index.ts @@ -28,7 +28,7 @@ export const resolveTimelineRoute = (router: SecuritySolutionPluginRouter) => { path: TIMELINE_RESOLVE_URL, security: { authz: { - requiredPrivileges: ['securitySolution'], + requiredPrivileges: ['timeline_read'], }, }, access: 'public', diff --git a/x-pack/solutions/security/plugins/security_solution/server/request_context_factory.ts b/x-pack/solutions/security/plugins/security_solution/server/request_context_factory.ts index 1c5e954dfeb79..8f8bab0bc45f7 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/request_context_factory.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/request_context_factory.ts @@ -33,6 +33,7 @@ import { createDetectionRulesClient } from './lib/detection_engine/rule_manageme import { buildMlAuthz } from './lib/machine_learning/authz'; import { EntityStoreDataClient } from './lib/entity_analytics/entity_store/entity_store_data_client'; import type { SiemMigrationsService } from './lib/siem_migrations/siem_migrations_service'; +import { AssetInventoryDataClient } from './lib/asset_inventory/asset_inventory_data_client'; export interface IRequestContextFactory { create( @@ -176,7 +177,13 @@ export class RequestContextFactory implements IRequestContextFactory { request, currentUser: coreContext.security.authc.getCurrentUser(), spaceId: getSpaceId(), - packageService: startPlugins.fleet?.packageService, + dependencies: { + inferenceClient: startPlugins.inference.getClient({ request }), + rulesClient, + actionsClient, + savedObjectsClient: coreContext.savedObjects.client, + packageService: startPlugins.fleet?.packageService, + }, }) ), @@ -242,6 +249,15 @@ export class RequestContextFactory implements IRequestContextFactory { telemetry: core.analytics, }); }), + getAssetInventoryClient: memoize(() => { + const clusterClient = coreContext.elasticsearch.client; + const logger = options.logger; + return new AssetInventoryDataClient({ + clusterClient, + logger, + experimentalFeatures: config.experimentalFeatures, + }); + }), }; } } diff --git a/x-pack/solutions/security/plugins/security_solution/server/routes/index.ts b/x-pack/solutions/security/plugins/security_solution/server/routes/index.ts index 6834e80ebc908..bd2e5cfdcad1d 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/routes/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/routes/index.ts @@ -53,6 +53,7 @@ import { registerTimelineRoutes } from '../lib/timeline/routes'; import { getFleetManagedIndexTemplatesRoute } from '../lib/security_integrations/cribl/routes'; import { registerEntityAnalyticsRoutes } from '../lib/entity_analytics/register_entity_analytics_routes'; import { registerSiemMigrationsRoutes } from '../lib/siem_migrations/routes'; +import { registerAssetInventoryRoutes } from '../lib/asset_inventory/routes'; export const initRoutes = ( router: SecuritySolutionPluginRouter, @@ -138,4 +139,6 @@ export const initRoutes = ( getFleetManagedIndexTemplatesRoute(router); registerWorkflowInsightsRoutes(router, config, endpointContext); + + registerAssetInventoryRoutes({ router, config, logger }); }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/saved_objects.ts b/x-pack/solutions/security/plugins/security_solution/server/saved_objects.ts index 9412e62e6315c..aaee168bf5ad6 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/saved_objects.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/saved_objects.ts @@ -33,6 +33,21 @@ const types = [ export const savedObjectTypes = types.map((type) => type.name); +export const savedObjectTypesWithoutTimelineAndWithoutNotes = savedObjectTypes.filter((type) => { + switch (type) { + case noteType.name: + case pinnedEventType.name: + case timelineType.name: + return false; + default: + return true; + } +}); + +export const timelineSavedObjectTypes = [timelineType.name, pinnedEventType.name]; + +export const notesSavedObjectTypes = [noteType.name]; + export const initSavedObjects = (savedObjects: CoreSetup['savedObjects']) => { types.forEach((type) => savedObjects.registerType(type)); }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/cti/event_enrichment/response.test.ts b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/cti/event_enrichment/response.test.ts index adddb12aa16e6..2591a48f22853 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/cti/event_enrichment/response.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/cti/event_enrichment/response.test.ts @@ -10,6 +10,7 @@ import { buildEventEnrichmentRawResponseMock, } from '../../../../../../common/search_strategy/security_solution/cti/index.mock'; import { parseEventEnrichmentResponse } from './response'; +import type { IEsSearchResponse } from '@kbn/search-types'; describe('parseEventEnrichmentResponse', () => { it('includes an accurate inspect response', async () => { @@ -101,4 +102,16 @@ describe('parseEventEnrichmentResponse', () => { }), ]); }); + + it('returns an empty array when no hits', async () => { + const options = buildEventEnrichmentRequestOptionsMock(); + const response = { + rawResponse: { + hits: {}, + }, + } as IEsSearchResponse; + const parsedResponse = await parseEventEnrichmentResponse(options, response); + + expect(parsedResponse.enrichments).toEqual([]); + }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/cti/event_enrichment/response.ts b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/cti/event_enrichment/response.ts index ebbff68d18cab..7be7694df8037 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/cti/event_enrichment/response.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/cti/event_enrichment/response.ts @@ -6,6 +6,8 @@ */ import type { IEsSearchResponse } from '@kbn/search-types'; +import { getOr } from 'lodash/fp'; +import type { SearchHit } from '@elastic/elasticsearch/lib/api/types'; import type { EventEnrichmentRequestOptions } from '../../../../../../common/api/search_strategy'; import { inspectStringifyObject } from '../../../../../utils/build_query'; import { buildIndicatorEnrichments, getTotalCount } from './helpers'; @@ -19,7 +21,8 @@ export const parseEventEnrichmentResponse = async ( dsl: [inspectStringifyObject(buildEventEnrichmentQuery(options))], }; const totalCount = getTotalCount(response.rawResponse.hits.total); - const enrichments = buildIndicatorEnrichments(response.rawResponse.hits.hits); + const hits: SearchHit[] = getOr([], 'rawResponse.hits.hits', response); + const enrichments = buildIndicatorEnrichments(hits); return { ...response, diff --git a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/index.ts b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/index.ts index 46ef72464dd1b..db853f87c0625 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/index.ts @@ -15,6 +15,7 @@ import { riskScoreFactory } from './risk_score'; import { usersFactory } from './users'; import { firstLastSeenFactory } from './last_first_seen'; import { relatedEntitiesFactory } from './related_entities'; +import { servicesFactory } from './services'; export const securitySolutionFactory: Record< FactoryQueryTypes, @@ -22,6 +23,7 @@ export const securitySolutionFactory: Record< > = { ...hostsFactory, ...usersFactory, + ...servicesFactory, ...networkFactory, ...ctiFactoryTypes, ...riskScoreFactory, diff --git a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/index.ts b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/index.ts new file mode 100644 index 0000000000000..4861c9b0e2f37 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ServicesQueries } from '../../../../../common/api/search_strategy'; +import type { FactoryQueryTypes } from '../../../../../common/search_strategy/security_solution'; + +import type { SecuritySolutionFactory } from '../types'; +import { observedServiceDetails } from './observed_details'; + +export const servicesFactory: Record< + ServicesQueries, + SecuritySolutionFactory +> = { + [ServicesQueries.observedDetails]: observedServiceDetails, +}; diff --git a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/__mocks__/index.ts b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/__mocks__/index.ts new file mode 100644 index 0000000000000..e9f98d217d700 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/__mocks__/index.ts @@ -0,0 +1,219 @@ +/* + * 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 { IEsSearchResponse } from '@kbn/search-types'; +import type { ObservedServiceDetailsRequestOptions } from '../../../../../../../common/api/search_strategy'; +import { ServicesQueries } from '../../../../../../../common/search_strategy/security_solution/services'; + +export const mockOptions: ObservedServiceDetailsRequestOptions = { + defaultIndex: ['test_indices*'], + factoryQueryType: ServicesQueries.observedDetails, + filterQuery: + '{"bool":{"must":[],"filter":[{"match_all":{}},{"match_phrase":{"service.name":{"query":"test_service"}}}],"should":[],"must_not":[]}}', + timerange: { + interval: '12h', + from: '2020-09-02T15:17:13.678Z', + to: '2020-09-03T15:17:13.678Z', + }, + params: {}, + serviceName: 'bastion00.siem.estc.dev', +} as ObservedServiceDetailsRequestOptions; + +export const mockSearchStrategyResponse: IEsSearchResponse = { + rawResponse: { + took: 1, + timed_out: false, + _shards: { + total: 2, + successful: 2, + skipped: 1, + failed: 0, + }, + hits: { + max_score: null, + hits: [], + }, + aggregations: { + aggregations: { + service_id: { + doc_count_error_upper_bound: -1, + sum_other_doc_count: 117, + buckets: [ + { + key: 'I30s36URfOdZ7gtpC4dum', + doc_count: 3, + timestamp: { + value: 1736851996820, + value_as_string: '2025-01-14T10:53:16.820Z', + }, + }, + ], + }, + service_name: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: 'Service-alarm', + doc_count: 147, + timestamp: { + value: 1736851996820, + value_as_string: '2025-01-14T10:53:16.820Z', + }, + }, + ], + }, + service_address: { + doc_count_error_upper_bound: -1, + sum_other_doc_count: 117, + buckets: [ + { + key: '15.103.138.105', + doc_count: 3, + timestamp: { + value: 1736851996820, + value_as_string: '2025-01-14T10:53:16.820Z', + }, + }, + ], + }, + service_environment: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: 'development', + doc_count: 57, + timestamp: { + value: 1736851996820, + value_as_string: '2025-01-14T10:53:16.820Z', + }, + }, + ], + }, + service_ephemeral_id: { + doc_count_error_upper_bound: -1, + sum_other_doc_count: 117, + buckets: [ + { + key: 'EV8lINfcelHgHrJMwuNvQ', + doc_count: 3, + timestamp: { + value: 1736851996820, + value_as_string: '2025-01-14T10:53:16.820Z', + }, + }, + ], + }, + service_node_name: { + doc_count_error_upper_bound: -1, + sum_other_doc_count: 117, + buckets: [ + { + key: 'corny-edger', + doc_count: 3, + timestamp: { + value: 1736851996820, + value_as_string: '2025-01-14T10:53:16.820Z', + }, + }, + ], + }, + service_node_roles: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: 'data', + doc_count: 42, + timestamp: { + value: 1736851996820, + value_as_string: '2025-01-14T10:53:16.820Z', + }, + }, + { + key: 'ingest', + doc_count: 54, + timestamp: { + value: 1736851996820, + value_as_string: '2025-01-14T10:53:16.820Z', + }, + }, + { + key: 'master', + doc_count: 51, + timestamp: { + value: 1736851996820, + value_as_string: '2025-01-14T10:53:16.820Z', + }, + }, + ], + }, + service_node_role: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: 'ingest', + doc_count: 30, + timestamp: { + value: 1736851996820, + value_as_string: '2025-01-14T10:53:16.820Z', + }, + }, + ], + }, + service_state: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: 'running', + doc_count: 51, + timestamp: { + value: 1736851996820, + value_as_string: '2025-01-14T10:53:16.820Z', + }, + }, + ], + }, + service_type: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: 'system', + doc_count: 147, + timestamp: { + value: 1736851996820, + value_as_string: '2025-01-14T10:53:16.820Z', + }, + }, + ], + }, + service_version: { + doc_count_error_upper_bound: -1, + sum_other_doc_count: 117, + buckets: [ + { + key: '2.1.9', + doc_count: 3, + timestamp: { + value: 1736851996820, + value_as_string: '2025-01-14T10:53:16.820Z', + }, + }, + ], + }, + }, + }, + }, + isPartial: false, + isRunning: false, + total: 2, + loaded: 2, +}; diff --git a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/__snapshots__/index.test.ts.snap b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/__snapshots__/index.test.ts.snap new file mode 100644 index 0000000000000..3b93b454c8b3d --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/__snapshots__/index.test.ts.snap @@ -0,0 +1,431 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`serviceDetails search strategy parse should parse data correctly 1`] = ` +Object { + "inspect": Object { + "dsl": Array [ + "{ + \\"allow_no_indices\\": true, + \\"index\\": [ + \\"test_indices*\\" + ], + \\"ignore_unavailable\\": true, + \\"track_total_hits\\": false, + \\"body\\": { + \\"aggregations\\": { + \\"service_id\\": { + \\"terms\\": { + \\"field\\": \\"service.id\\", + \\"size\\": 10, + \\"order\\": { + \\"timestamp\\": \\"desc\\" + } + }, + \\"aggs\\": { + \\"timestamp\\": { + \\"max\\": { + \\"field\\": \\"@timestamp\\" + } + } + } + }, + \\"service_name\\": { + \\"terms\\": { + \\"field\\": \\"service.name\\", + \\"size\\": 10, + \\"order\\": { + \\"timestamp\\": \\"desc\\" + } + }, + \\"aggs\\": { + \\"timestamp\\": { + \\"max\\": { + \\"field\\": \\"@timestamp\\" + } + } + } + }, + \\"service_address\\": { + \\"terms\\": { + \\"field\\": \\"service.address\\", + \\"size\\": 10, + \\"order\\": { + \\"timestamp\\": \\"desc\\" + } + }, + \\"aggs\\": { + \\"timestamp\\": { + \\"max\\": { + \\"field\\": \\"@timestamp\\" + } + } + } + }, + \\"service_environment\\": { + \\"terms\\": { + \\"field\\": \\"service.environment\\", + \\"size\\": 10, + \\"order\\": { + \\"timestamp\\": \\"desc\\" + } + }, + \\"aggs\\": { + \\"timestamp\\": { + \\"max\\": { + \\"field\\": \\"@timestamp\\" + } + } + } + }, + \\"service_ephemeral_id\\": { + \\"terms\\": { + \\"field\\": \\"service.ephemeral_id\\", + \\"size\\": 10, + \\"order\\": { + \\"timestamp\\": \\"desc\\" + } + }, + \\"aggs\\": { + \\"timestamp\\": { + \\"max\\": { + \\"field\\": \\"@timestamp\\" + } + } + } + }, + \\"service_node_name\\": { + \\"terms\\": { + \\"field\\": \\"service.node.name\\", + \\"size\\": 10, + \\"order\\": { + \\"timestamp\\": \\"desc\\" + } + }, + \\"aggs\\": { + \\"timestamp\\": { + \\"max\\": { + \\"field\\": \\"@timestamp\\" + } + } + } + }, + \\"service_node_roles\\": { + \\"terms\\": { + \\"field\\": \\"service.node.roles\\", + \\"size\\": 10, + \\"order\\": { + \\"timestamp\\": \\"desc\\" + } + }, + \\"aggs\\": { + \\"timestamp\\": { + \\"max\\": { + \\"field\\": \\"@timestamp\\" + } + } + } + }, + \\"service_node_role\\": { + \\"terms\\": { + \\"field\\": \\"service.node.role\\", + \\"size\\": 10, + \\"order\\": { + \\"timestamp\\": \\"desc\\" + } + }, + \\"aggs\\": { + \\"timestamp\\": { + \\"max\\": { + \\"field\\": \\"@timestamp\\" + } + } + } + }, + \\"service_state\\": { + \\"terms\\": { + \\"field\\": \\"service.state\\", + \\"size\\": 10, + \\"order\\": { + \\"timestamp\\": \\"desc\\" + } + }, + \\"aggs\\": { + \\"timestamp\\": { + \\"max\\": { + \\"field\\": \\"@timestamp\\" + } + } + } + }, + \\"service_type\\": { + \\"terms\\": { + \\"field\\": \\"service.type\\", + \\"size\\": 10, + \\"order\\": { + \\"timestamp\\": \\"desc\\" + } + }, + \\"aggs\\": { + \\"timestamp\\": { + \\"max\\": { + \\"field\\": \\"@timestamp\\" + } + } + } + }, + \\"service_version\\": { + \\"terms\\": { + \\"field\\": \\"service.version\\", + \\"size\\": 10, + \\"order\\": { + \\"timestamp\\": \\"desc\\" + } + }, + \\"aggs\\": { + \\"timestamp\\": { + \\"max\\": { + \\"field\\": \\"@timestamp\\" + } + } + } + } + }, + \\"query\\": { + \\"bool\\": { + \\"filter\\": [ + { + \\"bool\\": { + \\"must\\": [], + \\"filter\\": [ + { + \\"match_all\\": {} + }, + { + \\"match_phrase\\": { + \\"service.name\\": { + \\"query\\": \\"test_service\\" + } + } + } + ], + \\"should\\": [], + \\"must_not\\": [] + } + }, + { + \\"term\\": { + \\"service.name\\": \\"bastion00.siem.estc.dev\\" + } + }, + { + \\"range\\": { + \\"@timestamp\\": { + \\"format\\": \\"strict_date_optional_time\\", + \\"gte\\": \\"2020-09-02T15:17:13.678Z\\", + \\"lte\\": \\"2020-09-03T15:17:13.678Z\\" + } + } + } + ] + } + }, + \\"size\\": 0 + } +}", + ], + }, + "isPartial": false, + "isRunning": false, + "loaded": 2, + "rawResponse": Object { + "_shards": Object { + "failed": 0, + "skipped": 1, + "successful": 2, + "total": 2, + }, + "aggregations": Object { + "aggregations": Object { + "service_address": Object { + "buckets": Array [ + Object { + "doc_count": 3, + "key": "15.103.138.105", + "timestamp": Object { + "value": 1736851996820, + "value_as_string": "2025-01-14T10:53:16.820Z", + }, + }, + ], + "doc_count_error_upper_bound": -1, + "sum_other_doc_count": 117, + }, + "service_environment": Object { + "buckets": Array [ + Object { + "doc_count": 57, + "key": "development", + "timestamp": Object { + "value": 1736851996820, + "value_as_string": "2025-01-14T10:53:16.820Z", + }, + }, + ], + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + }, + "service_ephemeral_id": Object { + "buckets": Array [ + Object { + "doc_count": 3, + "key": "EV8lINfcelHgHrJMwuNvQ", + "timestamp": Object { + "value": 1736851996820, + "value_as_string": "2025-01-14T10:53:16.820Z", + }, + }, + ], + "doc_count_error_upper_bound": -1, + "sum_other_doc_count": 117, + }, + "service_id": Object { + "buckets": Array [ + Object { + "doc_count": 3, + "key": "I30s36URfOdZ7gtpC4dum", + "timestamp": Object { + "value": 1736851996820, + "value_as_string": "2025-01-14T10:53:16.820Z", + }, + }, + ], + "doc_count_error_upper_bound": -1, + "sum_other_doc_count": 117, + }, + "service_name": Object { + "buckets": Array [ + Object { + "doc_count": 147, + "key": "Service-alarm", + "timestamp": Object { + "value": 1736851996820, + "value_as_string": "2025-01-14T10:53:16.820Z", + }, + }, + ], + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + }, + "service_node_name": Object { + "buckets": Array [ + Object { + "doc_count": 3, + "key": "corny-edger", + "timestamp": Object { + "value": 1736851996820, + "value_as_string": "2025-01-14T10:53:16.820Z", + }, + }, + ], + "doc_count_error_upper_bound": -1, + "sum_other_doc_count": 117, + }, + "service_node_role": Object { + "buckets": Array [ + Object { + "doc_count": 30, + "key": "ingest", + "timestamp": Object { + "value": 1736851996820, + "value_as_string": "2025-01-14T10:53:16.820Z", + }, + }, + ], + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + }, + "service_node_roles": Object { + "buckets": Array [ + Object { + "doc_count": 42, + "key": "data", + "timestamp": Object { + "value": 1736851996820, + "value_as_string": "2025-01-14T10:53:16.820Z", + }, + }, + Object { + "doc_count": 54, + "key": "ingest", + "timestamp": Object { + "value": 1736851996820, + "value_as_string": "2025-01-14T10:53:16.820Z", + }, + }, + Object { + "doc_count": 51, + "key": "master", + "timestamp": Object { + "value": 1736851996820, + "value_as_string": "2025-01-14T10:53:16.820Z", + }, + }, + ], + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + }, + "service_state": Object { + "buckets": Array [ + Object { + "doc_count": 51, + "key": "running", + "timestamp": Object { + "value": 1736851996820, + "value_as_string": "2025-01-14T10:53:16.820Z", + }, + }, + ], + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + }, + "service_type": Object { + "buckets": Array [ + Object { + "doc_count": 147, + "key": "system", + "timestamp": Object { + "value": 1736851996820, + "value_as_string": "2025-01-14T10:53:16.820Z", + }, + }, + ], + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + }, + "service_version": Object { + "buckets": Array [ + Object { + "doc_count": 3, + "key": "2.1.9", + "timestamp": Object { + "value": 1736851996820, + "value_as_string": "2025-01-14T10:53:16.820Z", + }, + }, + ], + "doc_count_error_upper_bound": -1, + "sum_other_doc_count": 117, + }, + }, + }, + "hits": Object { + "hits": Array [], + "max_score": null, + }, + "timed_out": false, + "took": 1, + }, + "serviceDetails": Object {}, + "total": 2, +} +`; diff --git a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/__snapshots__/query.observed_service_details.dsl.test.ts.snap b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/__snapshots__/query.observed_service_details.dsl.test.ts.snap new file mode 100644 index 0000000000000..1933022563dd8 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/__snapshots__/query.observed_service_details.dsl.test.ts.snap @@ -0,0 +1,232 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`buildServiceDetailsQuery build query from options correctly 1`] = ` +Object { + "allow_no_indices": true, + "body": Object { + "aggregations": Object { + "service_address": Object { + "aggs": Object { + "timestamp": Object { + "max": Object { + "field": "@timestamp", + }, + }, + }, + "terms": Object { + "field": "service.address", + "order": Object { + "timestamp": "desc", + }, + "size": 10, + }, + }, + "service_environment": Object { + "aggs": Object { + "timestamp": Object { + "max": Object { + "field": "@timestamp", + }, + }, + }, + "terms": Object { + "field": "service.environment", + "order": Object { + "timestamp": "desc", + }, + "size": 10, + }, + }, + "service_ephemeral_id": Object { + "aggs": Object { + "timestamp": Object { + "max": Object { + "field": "@timestamp", + }, + }, + }, + "terms": Object { + "field": "service.ephemeral_id", + "order": Object { + "timestamp": "desc", + }, + "size": 10, + }, + }, + "service_id": Object { + "aggs": Object { + "timestamp": Object { + "max": Object { + "field": "@timestamp", + }, + }, + }, + "terms": Object { + "field": "service.id", + "order": Object { + "timestamp": "desc", + }, + "size": 10, + }, + }, + "service_name": Object { + "aggs": Object { + "timestamp": Object { + "max": Object { + "field": "@timestamp", + }, + }, + }, + "terms": Object { + "field": "service.name", + "order": Object { + "timestamp": "desc", + }, + "size": 10, + }, + }, + "service_node_name": Object { + "aggs": Object { + "timestamp": Object { + "max": Object { + "field": "@timestamp", + }, + }, + }, + "terms": Object { + "field": "service.node.name", + "order": Object { + "timestamp": "desc", + }, + "size": 10, + }, + }, + "service_node_role": Object { + "aggs": Object { + "timestamp": Object { + "max": Object { + "field": "@timestamp", + }, + }, + }, + "terms": Object { + "field": "service.node.role", + "order": Object { + "timestamp": "desc", + }, + "size": 10, + }, + }, + "service_node_roles": Object { + "aggs": Object { + "timestamp": Object { + "max": Object { + "field": "@timestamp", + }, + }, + }, + "terms": Object { + "field": "service.node.roles", + "order": Object { + "timestamp": "desc", + }, + "size": 10, + }, + }, + "service_state": Object { + "aggs": Object { + "timestamp": Object { + "max": Object { + "field": "@timestamp", + }, + }, + }, + "terms": Object { + "field": "service.state", + "order": Object { + "timestamp": "desc", + }, + "size": 10, + }, + }, + "service_type": Object { + "aggs": Object { + "timestamp": Object { + "max": Object { + "field": "@timestamp", + }, + }, + }, + "terms": Object { + "field": "service.type", + "order": Object { + "timestamp": "desc", + }, + "size": 10, + }, + }, + "service_version": Object { + "aggs": Object { + "timestamp": Object { + "max": Object { + "field": "@timestamp", + }, + }, + }, + "terms": Object { + "field": "service.version", + "order": Object { + "timestamp": "desc", + }, + "size": 10, + }, + }, + }, + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "filter": Array [ + Object { + "match_all": Object {}, + }, + Object { + "match_phrase": Object { + "service.name": Object { + "query": "test_service", + }, + }, + }, + ], + "must": Array [], + "must_not": Array [], + "should": Array [], + }, + }, + Object { + "term": Object { + "service.name": "bastion00.siem.estc.dev", + }, + }, + Object { + "range": Object { + "@timestamp": Object { + "format": "strict_date_optional_time", + "gte": "2020-09-02T15:17:13.678Z", + "lte": "2020-09-03T15:17:13.678Z", + }, + }, + }, + ], + }, + }, + "size": 0, + }, + "ignore_unavailable": true, + "index": Array [ + "test_indices*", + ], + "track_total_hits": false, +} +`; diff --git a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/helper.test.ts b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/helper.test.ts new file mode 100644 index 0000000000000..52f9d7f2549f1 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/helper.test.ts @@ -0,0 +1,33 @@ +/* + * 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 { ServiceAggEsItem } from '../../../../../../common/search_strategy/security_solution/services/common'; +import { fieldNameToAggField, formatServiceItem } from './helpers'; + +describe('helpers', () => { + it('it convert field name to aggregation field name', () => { + expect(fieldNameToAggField('service.node.role')).toBe('service_node_role'); + }); + + it('it formats ServiceItem', () => { + const serviceId = '123'; + const aggregations: ServiceAggEsItem = { + service_id: { + buckets: [ + { + key: serviceId, + doc_count: 1, + }, + ], + }, + }; + + expect(formatServiceItem(aggregations)).toEqual({ + service: { id: [serviceId] }, + }); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/helpers.ts b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/helpers.ts new file mode 100644 index 0000000000000..c5d2ba8084d05 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/helpers.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 { set } from '@kbn/safer-lodash-set/fp'; +import { get, has } from 'lodash/fp'; +import type { + ServiceAggEsItem, + ServiceBuckets, + ServiceItem, +} from '../../../../../../common/search_strategy/security_solution/services/common'; + +export const SERVICE_FIELDS = [ + 'service.id', + 'service.name', + 'service.address', + 'service.environment', + 'service.ephemeral_id', + 'service.node.name', + 'service.node.roles', + 'service.node.role', + 'service.state', + 'service.type', + 'service.version', +]; + +export const fieldNameToAggField = (fieldName: string) => fieldName.replace(/\./g, '_'); + +export const formatServiceItem = (aggregations: ServiceAggEsItem): ServiceItem => { + return SERVICE_FIELDS.reduce((flattenedFields, fieldName) => { + const aggField = fieldNameToAggField(fieldName); + + if (has(aggField, aggregations)) { + const data: ServiceBuckets = get(aggField, aggregations); + const fieldValue = data.buckets.map((obj) => obj.key); + + return set(fieldName, fieldValue, flattenedFields); + } + return flattenedFields; + }, {}); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/index.test.ts b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/index.test.ts new file mode 100644 index 0000000000000..1c2c0ff1ead4e --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/index.test.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as buildQuery from './query.observed_service_details.dsl'; +import { observedServiceDetails } from '.'; +import { mockOptions, mockSearchStrategyResponse } from './__mocks__'; + +describe('serviceDetails search strategy', () => { + const buildServiceDetailsQuery = jest.spyOn(buildQuery, 'buildObservedServiceDetailsQuery'); + + afterEach(() => { + buildServiceDetailsQuery.mockClear(); + }); + + describe('buildDsl', () => { + test('should build dsl query', () => { + observedServiceDetails.buildDsl(mockOptions); + expect(buildServiceDetailsQuery).toHaveBeenCalledWith(mockOptions); + }); + }); + + describe('parse', () => { + test('should parse data correctly', async () => { + const result = await observedServiceDetails.parse(mockOptions, mockSearchStrategyResponse); + expect(result).toMatchSnapshot(); + }); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/index.ts b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/index.ts new file mode 100644 index 0000000000000..62889f2011f9e --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/index.ts @@ -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 type { IEsSearchResponse } from '@kbn/search-types'; + +import { inspectStringifyObject } from '../../../../../utils/build_query'; +import type { SecuritySolutionFactory } from '../../types'; +import { buildObservedServiceDetailsQuery } from './query.observed_service_details.dsl'; + +import type { ServicesQueries } from '../../../../../../common/search_strategy/security_solution/services'; +import type { ObservedServiceDetailsStrategyResponse } from '../../../../../../common/search_strategy/security_solution/services/observed_details'; +import { formatServiceItem } from './helpers'; + +export const observedServiceDetails: SecuritySolutionFactory = { + buildDsl: (options) => buildObservedServiceDetailsQuery(options), + parse: async ( + options, + response: IEsSearchResponse + ): Promise => { + const aggregations = response.rawResponse.aggregations; + + const inspect = { + dsl: [inspectStringifyObject(buildObservedServiceDetailsQuery(options))], + }; + + if (aggregations == null) { + return { ...response, inspect, serviceDetails: {} }; + } + + return { + ...response, + inspect, + serviceDetails: formatServiceItem(aggregations), + }; + }, +}; diff --git a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/query.observed_service_details.dsl.test.ts b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/query.observed_service_details.dsl.test.ts new file mode 100644 index 0000000000000..50eff0367a89c --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/query.observed_service_details.dsl.test.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 { buildObservedServiceDetailsQuery } from './query.observed_service_details.dsl'; +import { mockOptions } from './__mocks__'; + +describe('buildServiceDetailsQuery', () => { + test('build query from options correctly', () => { + expect(buildObservedServiceDetailsQuery(mockOptions)).toMatchSnapshot(); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/query.observed_service_details.dsl.ts b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/query.observed_service_details.dsl.ts new file mode 100644 index 0000000000000..67155afe78c82 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/factory/services/observed_details/query.observed_service_details.dsl.ts @@ -0,0 +1,50 @@ +/* + * 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 { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { ISearchRequestParams } from '@kbn/search-types'; +import type { ObservedServiceDetailsRequestOptions } from '../../../../../../common/api/search_strategy'; +import { createQueryFilterClauses } from '../../../../../utils/build_query'; +import { buildFieldsTermAggregation } from '../../hosts/details/helpers'; +import { SERVICE_FIELDS } from './helpers'; + +export const buildObservedServiceDetailsQuery = ({ + serviceName, + defaultIndex, + timerange: { from, to }, + filterQuery, +}: ObservedServiceDetailsRequestOptions): ISearchRequestParams => { + const filter: QueryDslQueryContainer[] = [ + ...createQueryFilterClauses(filterQuery), + { term: { 'service.name': serviceName } }, + { + range: { + '@timestamp': { + format: 'strict_date_optional_time', + gte: from, + lte: to, + }, + }, + }, + ]; + + const dslQuery = { + allow_no_indices: true, + index: defaultIndex, + ignore_unavailable: true, + track_total_hits: false, + body: { + aggregations: { + ...buildFieldsTermAggregation(SERVICE_FIELDS), + }, + query: { bool: { filter } }, + size: 0, + }, + }; + + return dslQuery; +}; diff --git a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/index.ts b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/index.ts index 00393e2e6187e..5c8c4444dd761 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/search_strategy/security_solution/index.ts @@ -29,6 +29,8 @@ export const securitySolutionSearchStrategyProvider = ( search: (request, options, deps) => { const parsedRequest = searchStrategyRequestSchema.parse(request); const queryFactory = securitySolutionFactory[parsedRequest.factoryQueryType]; + // NOTE: without this parameter, .hits.hits can be empty + options.retrieveResults = true; const dsl = queryFactory.buildDsl(parsedRequest); return es.search({ ...request, params: dsl }, options, deps).pipe( diff --git a/x-pack/solutions/security/plugins/security_solution/server/types.ts b/x-pack/solutions/security/plugins/security_solution/server/types.ts index 72c8aa2a386e2..cf6dd27591501 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/types.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/types.ts @@ -38,6 +38,7 @@ import type { AssetCriticalityDataClient } from './lib/entity_analytics/asset_cr import type { IDetectionRulesClient } from './lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client_interface'; import type { EntityStoreDataClient } from './lib/entity_analytics/entity_store/entity_store_data_client'; import type { SiemRuleMigrationsClient } from './lib/siem_migrations/rules/siem_rule_migrations_service'; +import type { AssetInventoryDataClient } from './lib/asset_inventory/asset_inventory_data_client'; export { AppClient }; export interface SecuritySolutionApiRequestHandlerContext { @@ -63,6 +64,7 @@ export interface SecuritySolutionApiRequestHandlerContext { getEntityStoreDataClient: () => EntityStoreDataClient; getSiemRuleMigrationsClient: () => SiemRuleMigrationsClient; getInferenceClient: () => InferenceClient; + getAssetInventoryClient: () => AssetInventoryDataClient; } export type SecuritySolutionRequestHandlerContext = CustomRequestHandlerContext<{ diff --git a/x-pack/solutions/security/plugins/security_solution_ess/server/product_features/index.ts b/x-pack/solutions/security/plugins/security_solution_ess/server/product_features/index.ts index ed85c32f12284..a29ea4b9e2833 100644 --- a/x-pack/solutions/security/plugins/security_solution_ess/server/product_features/index.ts +++ b/x-pack/solutions/security/plugins/security_solution_ess/server/product_features/index.ts @@ -11,6 +11,8 @@ import { getCasesProductFeaturesConfigurator } from './cases_product_features_co import { getSecurityProductFeaturesConfigurator } from './security_product_features_config'; import { getSecurityAssistantProductFeaturesConfigurator } from './assistant_product_features_config'; import { getAttackDiscoveryProductFeaturesConfigurator } from './attack_discovery_product_features_config'; +import { getTimelineProductFeaturesConfigurator } from './timeline_product_features_config'; +import { getNotesProductFeaturesConfigurator } from './notes_product_features_config'; export const getProductProductFeaturesConfigurator = ( enabledProductFeatureKeys: ProductFeatureKeys @@ -20,5 +22,7 @@ export const getProductProductFeaturesConfigurator = ( security: getSecurityProductFeaturesConfigurator(enabledProductFeatureKeys), cases: getCasesProductFeaturesConfigurator(enabledProductFeatureKeys), securityAssistant: getSecurityAssistantProductFeaturesConfigurator(enabledProductFeatureKeys), + timeline: getTimelineProductFeaturesConfigurator(enabledProductFeatureKeys), + notes: getNotesProductFeaturesConfigurator(enabledProductFeatureKeys), }; }; diff --git a/x-pack/solutions/security/plugins/security_solution_ess/server/product_features/notes_product_features_config.ts b/x-pack/solutions/security/plugins/security_solution_ess/server/product_features/notes_product_features_config.ts new file mode 100644 index 0000000000000..0b9f1e143044a --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution_ess/server/product_features/notes_product_features_config.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 { + ProductFeatureKeys, + ProductFeatureKibanaConfig, + ProductFeaturesNotesConfig, +} from '@kbn/security-solution-features'; +import { + notesDefaultProductFeaturesConfig, + createEnabledProductFeaturesConfigMap, +} from '@kbn/security-solution-features/config'; +import type { ProductFeatureNotesFeatureKey } from '@kbn/security-solution-features/keys'; + +/** + * Maps the ProductFeatures keys to Kibana privileges that will be merged + * into the base privileges config for the app. + * + * Privileges can be added in different ways: + * - `privileges`: the privileges that will be added directly into the main Attack discovery feature. + * - `subFeatureIds`: the ids of the sub-features that will be added into the Attack discovery subFeatures entry. + * - `subFeaturesPrivileges`: the privileges that will be added into the existing Attack discovery subFeature with the privilege `id` specified. + */ +const notesProductFeaturesConfig: Record< + ProductFeatureNotesFeatureKey, + ProductFeatureKibanaConfig +> = { + ...notesDefaultProductFeaturesConfig, + // ess-specific app features configs here +}; + +export const getNotesProductFeaturesConfigurator = + (enabledProductFeatureKeys: ProductFeatureKeys) => (): ProductFeaturesNotesConfig => + createEnabledProductFeaturesConfigMap(notesProductFeaturesConfig, enabledProductFeatureKeys); diff --git a/x-pack/solutions/security/plugins/security_solution_ess/server/product_features/timeline_product_features_config.ts b/x-pack/solutions/security/plugins/security_solution_ess/server/product_features/timeline_product_features_config.ts new file mode 100644 index 0000000000000..411c06ecfe75f --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution_ess/server/product_features/timeline_product_features_config.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. + */ + +import type { + ProductFeatureKeys, + ProductFeatureKibanaConfig, + ProductFeaturesTimelineConfig, +} from '@kbn/security-solution-features'; +import { + createEnabledProductFeaturesConfigMap, + timelineDefaultProductFeaturesConfig, +} from '@kbn/security-solution-features/config'; +import type { ProductFeatureTimelineFeatureKey } from '@kbn/security-solution-features/keys'; + +/** + * Maps the ProductFeatures keys to Kibana privileges that will be merged + * into the base privileges config for the Security app. + * + * Privileges can be added in different ways: + * - `privileges`: the privileges that will be added directly into the main Attack discovery feature. + * - `subFeatureIds`: the ids of the sub-features that will be added into the Attack discovery subFeatures entry. + * - `subFeaturesPrivileges`: the privileges that will be added into the existing Attack discovery subFeature with the privilege `id` specified. + */ +const timelineProductFeaturesConfig: Record< + ProductFeatureTimelineFeatureKey, + ProductFeatureKibanaConfig +> = { + ...timelineDefaultProductFeaturesConfig, + // ess-specific app features configs here +}; + +export const getTimelineProductFeaturesConfigurator = + (enabledProductFeatureKeys: ProductFeatureKeys) => (): ProductFeaturesTimelineConfig => + createEnabledProductFeaturesConfigMap(timelineProductFeaturesConfig, enabledProductFeatureKeys); diff --git a/x-pack/solutions/security/plugins/security_solution_serverless/server/product_features/index.ts b/x-pack/solutions/security/plugins/security_solution_serverless/server/product_features/index.ts index 310ea860787ba..176003cfda14a 100644 --- a/x-pack/solutions/security/plugins/security_solution_serverless/server/product_features/index.ts +++ b/x-pack/solutions/security/plugins/security_solution_serverless/server/product_features/index.ts @@ -13,6 +13,8 @@ import { getAttackDiscoveryProductFeaturesConfigurator } from './attack_discover import { getCasesProductFeaturesConfigurator } from './cases_product_features_config'; import { getSecurityProductFeaturesConfigurator } from './security_product_features_config'; import { getSecurityAssistantProductFeaturesConfigurator } from './assistant_product_features_config'; +import { getTimelineProductFeaturesConfigurator } from './timeline_product_features_config'; +import { getNotesProductFeaturesConfigurator } from './notes_product_features_config'; import { enableRuleActions } from '../rules/enable_rule_actions'; import type { ServerlessSecurityConfig } from '../config'; import type { Tier, SecuritySolutionServerlessPluginSetupDeps } from '../types'; @@ -40,6 +42,8 @@ export const registerProductFeatures = ( ), cases: getCasesProductFeaturesConfigurator(enabledProductFeatureKeys), securityAssistant: getSecurityAssistantProductFeaturesConfigurator(enabledProductFeatureKeys), + timeline: getTimelineProductFeaturesConfigurator(enabledProductFeatureKeys), + notes: getNotesProductFeaturesConfigurator(enabledProductFeatureKeys), }); // enable rule actions based on the enabled product features diff --git a/x-pack/solutions/security/plugins/security_solution_serverless/server/product_features/notes_product_features_config.ts b/x-pack/solutions/security/plugins/security_solution_serverless/server/product_features/notes_product_features_config.ts new file mode 100644 index 0000000000000..1b00761f6da4a --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution_serverless/server/product_features/notes_product_features_config.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 { + ProductFeatureKeys, + ProductFeatureKibanaConfig, + ProductFeaturesNotesConfig, +} from '@kbn/security-solution-features'; +import { + notesDefaultProductFeaturesConfig, + createEnabledProductFeaturesConfigMap, +} from '@kbn/security-solution-features/config'; +import type { ProductFeatureNotesFeatureKey } from '@kbn/security-solution-features/keys'; + +/** + * Maps the ProductFeatures keys to Kibana privileges that will be merged + * into the base privileges config for the app. + * + * Privileges can be added in different ways: + * - `privileges`: the privileges that will be added directly into the main Attack discovery feature. + * - `subFeatureIds`: the ids of the sub-features that will be added into the Attack discovery subFeatures entry. + * - `subFeaturesPrivileges`: the privileges that will be added into the existing Attack discovery subFeature with the privilege `id` specified. + */ +const notesProductFeaturesConfig: Record< + ProductFeatureNotesFeatureKey, + ProductFeatureKibanaConfig +> = { + ...notesDefaultProductFeaturesConfig, + // serverless-specific app features configs here +}; + +export const getNotesProductFeaturesConfigurator = + (enabledProductFeatureKeys: ProductFeatureKeys) => (): ProductFeaturesNotesConfig => + createEnabledProductFeaturesConfigMap(notesProductFeaturesConfig, enabledProductFeatureKeys); diff --git a/x-pack/solutions/security/plugins/security_solution_serverless/server/product_features/timeline_product_features_config.ts b/x-pack/solutions/security/plugins/security_solution_serverless/server/product_features/timeline_product_features_config.ts new file mode 100644 index 0000000000000..fde220b83cb30 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution_serverless/server/product_features/timeline_product_features_config.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 { + ProductFeatureKeys, + ProductFeatureKibanaConfig, + ProductFeaturesTimelineConfig, +} from '@kbn/security-solution-features'; +import { + timelineDefaultProductFeaturesConfig, + createEnabledProductFeaturesConfigMap, +} from '@kbn/security-solution-features/config'; +import type { ProductFeatureTimelineFeatureKey } from '@kbn/security-solution-features/keys'; + +/** + * Maps the ProductFeatures keys to Kibana privileges that will be merged + * into the base privileges config for the app. + * + * Privileges can be added in different ways: + * - `privileges`: the privileges that will be added directly into the main Attack discovery feature. + * - `subFeatureIds`: the ids of the sub-features that will be added into the Attack discovery subFeatures entry. + * - `subFeaturesPrivileges`: the privileges that will be added into the existing Attack discovery subFeature with the privilege `id` specified. + */ +const timelineProductFeaturesConfig: Record< + ProductFeatureTimelineFeatureKey, + ProductFeatureKibanaConfig +> = { + ...timelineDefaultProductFeaturesConfig, + // serverless-specific app features configs here +}; + +export const getTimelineProductFeaturesConfigurator = + (enabledProductFeatureKeys: ProductFeatureKeys) => (): ProductFeaturesTimelineConfig => + createEnabledProductFeaturesConfigMap(timelineProductFeaturesConfig, enabledProductFeatureKeys); diff --git a/x-pack/solutions/security/plugins/session_view/public/components/detail_panel_alert_actions/styles.ts b/x-pack/solutions/security/plugins/session_view/public/components/detail_panel_alert_actions/styles.ts deleted file mode 100644 index 14d0be374b5d1..0000000000000 --- a/x-pack/solutions/security/plugins/session_view/public/components/detail_panel_alert_actions/styles.ts +++ /dev/null @@ -1,107 +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 { useMemo } from 'react'; -import { useEuiTheme, transparentize } from '@elastic/eui'; -import { CSSObject, css } from '@emotion/react'; - -interface StylesDeps { - minimal?: boolean; - isInvestigated?: boolean; -} - -export const useStyles = ({ minimal = false, isInvestigated = false }: StylesDeps) => { - const { euiTheme } = useEuiTheme(); - - const cached = useMemo(() => { - const { colors, font, size, border } = euiTheme; - - const dangerBorder = transparentize(colors.danger, 0.2); - const dangerBackground = transparentize(colors.danger, 0.08); - const borderThickness = border.width.thin; - const mediumPadding = size.m; - - let alertTitleColor = colors.text; - let borderColor = colors.lightShade; - - if (isInvestigated) { - alertTitleColor = colors.primaryText; - borderColor = dangerBorder; - } - - const alertItem = css` - border: ${borderThickness} solid ${borderColor}; - padding: ${mediumPadding}; - border-radius: ${border.radius.medium}; - - margin: 0 ${mediumPadding} ${mediumPadding} ${mediumPadding}; - background-color: ${colors.emptyShade}; - - & .euiAccordion__buttonContent { - width: 100%; - } - - & .euiAccordion__button { - min-width: 0; - width: calc(100% - ${size.l}); - } - - & .euiAccordion__childWrapper { - overflow: visible; - } - `; - - const alertTitle: CSSObject = { - display: minimal ? 'none' : 'initial', - color: alertTitleColor, - fontWeight: font.weight.semiBold, - textOverflow: 'ellipsis', - overflow: 'hidden', - whiteSpace: 'nowrap', - }; - - const alertIcon: CSSObject = { - marginRight: size.s, - }; - - const alertAccordionButton: CSSObject = { - width: `calc(100% - ${size.l})`, - minWidth: 0, - }; - - const processPanel: CSSObject = { - border: `${borderThickness} solid ${colors.lightShade}`, - fontFamily: font.familyCode, - marginTop: mediumPadding, - padding: `${size.xs} ${size.s}`, - }; - - const investigatedLabel: CSSObject = { - position: 'relative', - zIndex: 1, - bottom: `-${mediumPadding}`, - left: `-${mediumPadding}`, - width: `calc(100% + ${mediumPadding} * 2)`, - borderTop: `${borderThickness} solid ${dangerBorder}`, - borderBottomLeftRadius: border.radius.medium, - borderBottomRightRadius: border.radius.medium, - backgroundColor: dangerBackground, - textAlign: 'center', - }; - - return { - alertItem, - alertTitle, - alertIcon, - alertAccordionButton, - processPanel, - investigatedLabel, - }; - }, [euiTheme, isInvestigated, minimal]); - - return cached; -}; diff --git a/x-pack/solutions/security/plugins/session_view/public/components/detail_panel_alert_list_item/styles.ts b/x-pack/solutions/security/plugins/session_view/public/components/detail_panel_alert_list_item/styles.ts index 4cd77e48c2c4d..85cb461bc9c16 100644 --- a/x-pack/solutions/security/plugins/session_view/public/components/detail_panel_alert_list_item/styles.ts +++ b/x-pack/solutions/security/plugins/session_view/public/components/detail_panel_alert_list_item/styles.ts @@ -15,8 +15,8 @@ export const useStyles = (minimal = false, isInvestigated = false) => { const cached = useMemo(() => { const { colors, font, size, border } = euiTheme; - const dangerBorder = transparentize(colors.danger, 0.2); - const dangerBackground = transparentize(colors.danger, 0.08); + const dangerBorder = transparentize(colors.danger, 0.2); // TODO: Borealis migration - replace transparentize with color token + const dangerBackground = transparentize(colors.danger, 0.08); // TODO: Borealis migration - replace transparentize with color token const borderThickness = border.width.thin; const mediumPadding = size.m; diff --git a/x-pack/solutions/security/plugins/session_view/public/components/detail_panel_list_item/styles.ts b/x-pack/solutions/security/plugins/session_view/public/components/detail_panel_list_item/styles.ts index 48a8dba781ee4..6823ba6bd0abd 100644 --- a/x-pack/solutions/security/plugins/session_view/public/components/detail_panel_list_item/styles.ts +++ b/x-pack/solutions/security/plugins/session_view/public/components/detail_panel_list_item/styles.ts @@ -41,7 +41,7 @@ export const useStyles = ({ display }: StylesDeps) => { position: 'relative', borderRadius: euiTheme.border.radius.medium, '&:hover': { - background: transparentize(euiTheme.colors.primary, 0.1), + background: transparentize(euiTheme.colors.primary, 0.1), // TODO: Borealis migration - replace transparentize with color token }, height: 'fit-content', }; diff --git a/x-pack/solutions/security/plugins/session_view/public/components/process_tree/styles.ts b/x-pack/solutions/security/plugins/session_view/public/components/process_tree/styles.ts index d01a906e1d38d..a2dac9bbb60ca 100644 --- a/x-pack/solutions/security/plugins/session_view/public/components/process_tree/styles.ts +++ b/x-pack/solutions/security/plugins/session_view/public/components/process_tree/styles.ts @@ -6,7 +6,6 @@ */ import { useMemo } from 'react'; -import { transparentize } from '@elastic/eui'; import { CSSObject } from '@emotion/react'; import { useEuiTheme } from '../../hooks'; @@ -14,8 +13,7 @@ export const useStyles = () => { const { euiTheme, euiVars } = useEuiTheme(); const cached = useMemo(() => { - const { colors, font, size } = euiTheme; - const defaultSelectionColor = colors.primary; + const { font } = euiTheme; const sessionViewProcessTree: CSSObject = { position: 'relative', @@ -25,26 +23,8 @@ export const useStyles = () => { backgroundColor: euiVars.euiColorLightestShade, }; - const selectionArea: CSSObject = { - position: 'absolute', - display: 'none', - marginLeft: '-50%', - width: '150%', - height: '100%', - backgroundColor: defaultSelectionColor, - pointerEvents: 'none', - opacity: 0.1, - transform: `translateY(-${size.xs})`, - }; - - const defaultSelected = transparentize(colors.primary, 0.008); - const alertSelected = transparentize(colors.danger, 0.008); - return { sessionViewProcessTree, - selectionArea, - defaultSelected, - alertSelected, }; }, [euiTheme, euiVars]); diff --git a/x-pack/solutions/security/plugins/session_view/public/components/process_tree_alert/styles.ts b/x-pack/solutions/security/plugins/session_view/public/components/process_tree_alert/styles.ts index de3dc797e3351..02d49e502bc35 100644 --- a/x-pack/solutions/security/plugins/session_view/public/components/process_tree_alert/styles.ts +++ b/x-pack/solutions/security/plugins/session_view/public/components/process_tree_alert/styles.ts @@ -23,17 +23,17 @@ export const useStyles = ({ isInvestigated, isSelected }: StylesDeps) => { const getHighlightColors = () => { let bgColor = 'none'; - let hoverBgColor = `${transparentize(colors.primary, 0.04)}`; + let hoverBgColor = `${transparentize(colors.primary, 0.04)}`; // TODO: Borealis migration - replace transparentize with color token if (isInvestigated && isSelected) { - bgColor = `${transparentize(colors.danger, 0.08)}`; - hoverBgColor = `${transparentize(colors.danger, 0.12)}`; + bgColor = `${transparentize(colors.danger, 0.08)}`; // TODO: Borealis migration - replace transparentize with color token + hoverBgColor = `${transparentize(colors.danger, 0.12)}`; // TODO: Borealis migration - replace transparentize with color token } else if (isInvestigated) { - bgColor = `${transparentize(colors.danger, 0.04)}`; - hoverBgColor = `${transparentize(colors.danger, 0.12)}`; + bgColor = `${transparentize(colors.danger, 0.04)}`; // TODO: Borealis migration - replace transparentize with color token + hoverBgColor = `${transparentize(colors.danger, 0.12)}`; // TODO: Borealis migration - replace transparentize with color token } else if (isSelected) { - bgColor = `${transparentize(colors.primary, 0.08)}`; - hoverBgColor = `${transparentize(colors.primary, 0.12)}`; + bgColor = `${transparentize(colors.primary, 0.08)}`; // TODO: Borealis migration - replace transparentize with color token + hoverBgColor = `${transparentize(colors.primary, 0.12)}`; // TODO: Borealis migration - replace transparentize with color token } return { bgColor, hoverBgColor }; @@ -56,7 +56,7 @@ export const useStyles = ({ isInvestigated, isSelected }: StylesDeps) => { flexShrink: 0, marginRight: size.xs, '&:hover, &:focus, &:focus-within': { - backgroundColor: transparentize(euiVars.buttonsBackgroundNormalDefaultPrimary, 0.2), + backgroundColor: transparentize(euiVars.buttonsBackgroundNormalDefaultPrimary, 0.2), // TODO: Borealis migration - replace transparentize with color token }, }, '&& .euiFlexItem': { diff --git a/x-pack/solutions/security/plugins/session_view/public/components/process_tree_node/index.tsx b/x-pack/solutions/security/plugins/session_view/public/components/process_tree_node/index.tsx index b493591b94370..43f0c8e5a2763 100644 --- a/x-pack/solutions/security/plugins/session_view/public/components/process_tree_node/index.tsx +++ b/x-pack/solutions/security/plugins/session_view/public/components/process_tree_node/index.tsx @@ -5,12 +5,6 @@ * 2.0. */ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - *2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ import React, { useState, useEffect, diff --git a/x-pack/solutions/security/plugins/session_view/public/components/process_tree_node/styles.ts b/x-pack/solutions/security/plugins/session_view/public/components/process_tree_node/styles.ts index 32048cfd97585..56df551b2ffe5 100644 --- a/x-pack/solutions/security/plugins/session_view/public/components/process_tree_node/styles.ts +++ b/x-pack/solutions/security/plugins/session_view/public/components/process_tree_node/styles.ts @@ -58,9 +58,9 @@ export const useStyles = ({ */ const getHighlightColors = () => { let bgColor = 'none'; - let hoverColor = transparentize(colors.primary, 0.04); + let hoverColor = transparentize(colors.primary, 0.04); // TODO: Borealis migration - replace transparentize with color token let borderColor = 'transparent'; - let searchResColor = transparentize(colors.warning, 0.32); + let searchResColor = transparentize(colors.warning, 0.32); // TODO: Borealis migration - replace transparentize with color token if (hasAlerts) { borderColor = colors.danger; @@ -68,15 +68,15 @@ export const useStyles = ({ if (isSelected) { searchResColor = colors.warning; - bgColor = transparentize(colors.primary, 0.08); - hoverColor = transparentize(colors.primary, 0.12); + bgColor = transparentize(colors.primary, 0.08); // TODO: Borealis migration - replace transparentize with color token + hoverColor = transparentize(colors.primary, 0.12); // TODO: Borealis migration - replace transparentize with color token } if (hasInvestigatedAlert) { - bgColor = transparentize(colors.danger, 0.04); - hoverColor = transparentize(colors.danger, 0.12); + bgColor = transparentize(colors.danger, 0.04); // TODO: Borealis migration - replace transparentize with color token + hoverColor = transparentize(colors.danger, 0.12); // TODO: Borealis migration - replace transparentize with color token if (isSelected) { - bgColor = transparentize(colors.danger, 0.08); + bgColor = transparentize(colors.danger, 0.08); // TODO: Borealis migration - replace transparentize with color token } } @@ -166,7 +166,7 @@ export const useStyles = ({ }; const workingDir: CSSObject = { - color: colors.successText, + color: colors.textSuccess, fontFamily: font.familyCode, fontWeight: font.weight.regular, }; diff --git a/x-pack/solutions/security/plugins/session_view/public/components/process_tree_node/use_button_styles.ts b/x-pack/solutions/security/plugins/session_view/public/components/process_tree_node/use_button_styles.ts index c6e89f9be0d13..c5f574eb1befc 100644 --- a/x-pack/solutions/security/plugins/session_view/public/components/process_tree_node/use_button_styles.ts +++ b/x-pack/solutions/security/plugins/session_view/public/components/process_tree_node/use_button_styles.ts @@ -6,12 +6,11 @@ */ import { useMemo } from 'react'; -import { transparentize } from '@elastic/eui'; import { CSSObject } from '@emotion/react'; import { useEuiTheme } from '../../hooks'; export const useButtonStyles = () => { - const { euiTheme, euiVars } = useEuiTheme(); + const { euiTheme } = useEuiTheme(); const cached = useMemo(() => { const { border, colors, size, font } = euiTheme; @@ -27,9 +26,9 @@ export const useButtonStyles = () => { marginRight: size.xs, minWidth: 0, padding: `${size.s} ${size.xxs}`, - color: euiVars.euiColorVis6_asText, - background: transparentize(euiVars.euiColorVis6, 0.04), - border: `${border.width.thin} solid ${transparentize(euiVars.euiColorVis6, 0.48)}`, + color: colors.textPrimary, + background: colors.backgroundBasePrimary, + border: `${border.width.thin} solid ${colors.borderBasePrimary}`, '&& > span': { padding: `0px ${size.xxs}`, svg: { @@ -37,7 +36,7 @@ export const useButtonStyles = () => { }, }, '&&:hover, &&:focus': { - background: transparentize(euiVars.euiColorVis6, 0.12), + background: colors.backgroundLightPrimary, textDecoration: 'none', }, '&.isExpanded > span svg:not(.alertIcon)': { @@ -45,9 +44,9 @@ export const useButtonStyles = () => { }, '&.isExpanded': { color: colors.ghost, - background: euiVars.euiColorVis6, + background: colors.backgroundFilledPrimary, '&:hover, &:focus': { - background: euiVars.euiColorVis6, + background: colors.backgroundFilledPrimary, }, }, }; @@ -57,18 +56,18 @@ export const useButtonStyles = () => { }; const alertButton: CSSObject = { ...button, - color: euiVars.euiColorDanger, - background: transparentize(euiVars.euiColorDanger, 0.04), - border: `${border.width.thin} solid ${transparentize(euiVars.euiColorDanger, 0.48)}`, + color: colors.textDanger, + background: colors.backgroundBaseDanger, + border: `${border.width.thin} solid ${colors.borderBaseDanger}`, '&&:hover, &&:focus': { - background: transparentize(euiVars.euiColorDanger, 0.12), + background: colors.backgroundLightDanger, textDecoration: 'none', }, '&.isExpanded': { color: colors.ghost, - background: euiVars.euiColorDanger, + background: colors.backgroundFilledDanger, '&:hover, &:focus': { - background: `${euiVars.euiColorDanger}`, + background: `${colors.backgroundFilledDanger}`, }, }, @@ -83,18 +82,18 @@ export const useButtonStyles = () => { const outputButton: CSSObject = { ...button, - color: euiVars.euiColorVis1, - background: transparentize(euiVars.euiColorVis1, 0.04), - border: `${border.width.thin} solid ${transparentize(euiVars.euiColorVis1, 0.48)}`, + color: colors.textAccent, + background: colors.backgroundBaseAccent, + border: `${border.width.thin} solid ${colors.borderBaseAccent}`, '&&:hover, &&:focus': { - background: transparentize(euiVars.euiColorVis1, 0.12), + background: colors.backgroundLightAccent, textDecoration: 'none', }, '&.isExpanded': { color: colors.ghost, - background: euiVars.euiColorVis1, + background: colors.backgroundFilledAccent, '&:hover, &:focus': { - background: `${euiVars.euiColorVis1}`, + background: `${colors.backgroundFilledAccent}`, }, }, }; @@ -102,12 +101,12 @@ export const useButtonStyles = () => { const userChangedButton: CSSObject = { ...button, cursor: 'default', - color: euiVars.euiColorGhost, - background: euiVars.euiColorVis3, - border: `${border.width.thin} solid ${transparentize(euiVars.euiColorVis3, 0.48)}`, + color: colors.textAccentSecondary, + background: colors.backgroundBaseAccentSecondary, + border: `${border.width.thin} solid ${colors.borderBaseAccentSecondary}`, '&&:hover, &&:focus': { - color: euiVars.euiColorGhost, - background: euiVars.euiColorVis3, + color: colors.textAccentSecondary, + background: colors.backgroundBaseAccentSecondary, textDecoration: 'none', transform: 'none', animation: 'none', @@ -126,7 +125,7 @@ export const useButtonStyles = () => { userChangedButton, buttonSize, }; - }, [euiTheme, euiVars]); + }, [euiTheme]); return cached; }; diff --git a/x-pack/solutions/security/plugins/session_view/public/components/tty_player/hooks.test.tsx b/x-pack/solutions/security/plugins/session_view/public/components/tty_player/hooks.test.tsx index 5531210e10a3c..802b833c3e83f 100644 --- a/x-pack/solutions/security/plugins/session_view/public/components/tty_player/hooks.test.tsx +++ b/x-pack/solutions/security/plugins/session_view/public/components/tty_player/hooks.test.tsx @@ -63,38 +63,38 @@ describe('TTYPlayer/hooks', () => { }); it('mounts and renders the first line of output', async () => { - const { result: xTermResult } = renderHook((props) => useXtermPlayer(props), { + const { result: xTermResult } = renderHook(useXtermPlayer, { initialProps, }); const { terminal, currentLine, seekToLine } = xTermResult.current; // there is a minor delay in updates to xtermjs after writeln is called. - jest.advanceTimersByTime(100); + await act(async () => jest.advanceTimersByTime(100)); // check that first line rendered in xtermjs expect(terminal.buffer.active.getLine(0)?.translateToString(true)).toBe('256'); expect(currentLine).toBe(0); - act(() => { + await act(async () => { seekToLine(VIM_LINE_START); // line where vim output starts }); - jest.advanceTimersByTime(100); + await act(async () => jest.advanceTimersByTime(100)); expect(terminal.buffer.active.getLine(0)?.translateToString(true)).toBe('#!/bin/env bash'); }); it('allows the user to seek to any line of output', async () => { - const { result: xTermResult } = renderHook((props) => useXtermPlayer(props), { + const { result: xTermResult } = renderHook(useXtermPlayer, { initialProps, }); - act(() => { + await act(async () => { xTermResult.current.seekToLine(VIM_LINE_START); // line where vim output starts }); - jest.advanceTimersByTime(100); + await act(async () => jest.advanceTimersByTime(100)); const { terminal, currentLine } = xTermResult.current; @@ -103,64 +103,68 @@ describe('TTYPlayer/hooks', () => { }); it('allows the user to play', async () => { - const { result, rerender } = renderHook((props) => useXtermPlayer(props), { + const { result, rerender } = renderHook(useXtermPlayer, { initialProps, }); rerender({ ...initialProps, isPlaying: true }); - act(() => { - jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * 10); - }); + await act(async () => jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * 10)); expect(result.current.currentLine).toBe(10); }); it('allows the user to stop', async () => { - const { result, rerender } = renderHook((props) => useXtermPlayer(props), { + const { result, rerender } = renderHook(useXtermPlayer, { initialProps, }); rerender({ ...initialProps, isPlaying: true }); - act(() => { - jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * 10); - }); + + await act(async () => jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * 10)); + + expect(result.current.currentLine).toBe(10); + rerender({ ...initialProps, isPlaying: false }); - act(() => { - jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * 10); - }); + + await act(async () => jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * 10)); + expect(result.current.currentLine).toBe(10); // should not have advanced }); it('should stop when it reaches the end of the array of lines', async () => { - const { result, rerender } = renderHook((props) => useXtermPlayer(props), { + const { result, rerender } = renderHook(useXtermPlayer, { initialProps, }); rerender({ ...initialProps, isPlaying: true }); - act(() => { - jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * initialProps.lines.length + 100); - }); + + await act(async () => + jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * initialProps.lines.length + 100) + ); + expect(result.current.currentLine).toBe(initialProps.lines.length - 1); }); it('should not print the first line twice after playback starts', async () => { - const { result, rerender } = renderHook((props) => useXtermPlayer(props), { + const { result, rerender } = renderHook(useXtermPlayer, { initialProps, }); rerender({ ...initialProps, isPlaying: true }); - act(() => { + + await act(async () => { // advance render loop jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS); }); + rerender({ ...initialProps, isPlaying: false }); expect(result.current.terminal.buffer.active.getLine(0)?.translateToString(true)).toBe('256'); }); it('ensure the first few render loops have printed the right lines', async () => { - const { result, rerender } = renderHook((props) => useXtermPlayer(props), { + const { result, rerender } = renderHook(useXtermPlayer, { initialProps, }); @@ -168,7 +172,7 @@ describe('TTYPlayer/hooks', () => { rerender({ ...initialProps, isPlaying: true }); - act(() => { + await act(async () => { // advance render loop jest.advanceTimersByTime(DEFAULT_TTY_PLAYSPEED_MS * LOOPS); }); @@ -193,7 +197,7 @@ describe('TTYPlayer/hooks', () => { }); it('will allow a plain text search highlight on the last line printed', async () => { - const { result: xTermResult } = renderHook((props) => useXtermPlayer(props), { + const { result: xTermResult } = renderHook(useXtermPlayer, { initialProps, }); diff --git a/x-pack/solutions/security/plugins/session_view/public/components/tty_player/hooks.ts b/x-pack/solutions/security/plugins/session_view/public/components/tty_player/hooks.ts index a1f039f9caad0..7f67a49ab4659 100644 --- a/x-pack/solutions/security/plugins/session_view/public/components/tty_player/hooks.ts +++ b/x-pack/solutions/security/plugins/session_view/public/components/tty_player/hooks.ts @@ -318,21 +318,26 @@ export const useXtermPlayer = ({ useEffect(() => { if (isPlaying) { - const timer = setTimeout(() => { - if (!hasNextPage && currentLine === lines.length - 1) { - setIsPlaying(false); - } else { - const nextLine = Math.min(lines.length - 1, currentLine + 1); - render(nextLine, false); - setCurrentLine(nextLine); - } - }, playSpeed); + const timer = setInterval( + () => + setCurrentLine((_currentLine) => { + if (!hasNextPage && _currentLine === lines.length - 1) { + setIsPlaying(false); + return _currentLine; + } else { + const nextLine = Math.min(lines.length - 1, _currentLine + 1); + render(nextLine, false); + return nextLine; + } + }), + playSpeed + ); return () => { - clearTimeout(timer); + clearInterval(timer); }; } - }, [lines, currentLine, isPlaying, playSpeed, render, hasNextPage, fetchNextPage, setIsPlaying]); + }, [lines, isPlaying, playSpeed, render, hasNextPage, fetchNextPage, setIsPlaying]); const seekToLine = useCallback( (index: any) => { diff --git a/x-pack/solutions/security/plugins/session_view/public/components/tty_player/styles.ts b/x-pack/solutions/security/plugins/session_view/public/components/tty_player/styles.ts index cbc182c7efb53..f7b9ff88a4445 100644 --- a/x-pack/solutions/security/plugins/session_view/public/components/tty_player/styles.ts +++ b/x-pack/solutions/security/plugins/session_view/public/components/tty_player/styles.ts @@ -37,7 +37,7 @@ export const useStyles = (tty?: Teletype, show?: boolean) => { padding: `${size.m} ${size.base}`, }; - const windowBoundsColor = transparentize(colors.ghost, 0.6); + const windowBoundsColor = transparentize(colors.ghost, 0.6); // TODO: Borealis migration - replace transparentize with color token, get rid of ghost color const terminal: CSSObject = { minHeight: '100%', diff --git a/x-pack/solutions/security/plugins/session_view/public/components/tty_player_controls/tty_player_controls_markers/styles.ts b/x-pack/solutions/security/plugins/session_view/public/components/tty_player_controls/tty_player_controls_markers/styles.ts index 48c7c67128c64..dad8c34b52ffb 100644 --- a/x-pack/solutions/security/plugins/session_view/public/components/tty_player_controls/tty_player_controls_markers/styles.ts +++ b/x-pack/solutions/security/plugins/session_view/public/components/tty_player_controls/tty_player_controls_markers/styles.ts @@ -11,8 +11,13 @@ import { useEuiTheme } from '../../../hooks'; import { TTYPlayerLineMarkerType } from '.'; +const isAmsterdam = (euiThemeName: string) => { + return euiThemeName?.toLowerCase().includes('amsterdam'); +}; + export const useStyles = (progress: number) => { const { euiTheme, euiVars } = useEuiTheme(); + const themeName = euiTheme.themeName; const cached = useMemo(() => { const { border } = euiTheme; @@ -36,7 +41,7 @@ export const useStyles = (progress: number) => { if (selected) { return euiVars.terminalOutputMarkerAccent; } - return euiVars.euiColorVis1; + return isAmsterdam(themeName) ? euiVars.euiColorVis1 : euiVars.euiColorVis2; }; const marker = (type: TTYPlayerLineMarkerType, selected: boolean): CSSObject => ({ @@ -84,16 +89,24 @@ export const useStyles = (progress: number) => { "input[type='range']::-webkit-slider-thumb": customThumb, "input[type='range']::-moz-range-thumb": customThumb, '.euiRangeHighlight__progress': { - backgroundColor: euiVars.euiColorVis0_behindText, + backgroundColor: isAmsterdam(themeName) + ? euiVars.euiColorVis0_behindText + : euiVars.euiColorVis0, width: progress + '%!important', borderBottomRightRadius: 0, borderTopRightRadius: 0, }, '.euiRangeSlider:focus ~ .euiRangeHighlight .euiRangeHighlight__progress': { - backgroundColor: euiVars.euiColorVis0_behindText, + backgroundColor: isAmsterdam(themeName) + ? euiVars.euiColorVis0_behindText + : euiVars.euiColorVis0, }, '.euiRangeSlider:focus:not(:focus-visible) ~ .euiRangeHighlight .euiRangeHighlight__progress': - { backgroundColor: euiVars.euiColorVis0_behindText }, + { + backgroundColor: isAmsterdam(themeName) + ? euiVars.euiColorVis0_behindText + : euiVars.euiColorVis0, + }, '.euiRangeTrack::after': { background: euiVars.terminalOutputSliderBackground, }, @@ -120,12 +133,15 @@ export const useStyles = (progress: number) => { }, [ euiTheme, euiVars.euiColorVis0_behindText, + euiVars.euiColorVis0, euiVars.euiColorVis1, + euiVars.euiColorVis2, euiVars.terminalOutputBackground, euiVars.terminalOutputMarkerAccent, euiVars.terminalOutputMarkerWarning, euiVars.terminalOutputSliderBackground, progress, + themeName, ]); return cached; diff --git a/x-pack/solutions/security/plugins/session_view/public/hooks/use_eui_theme.ts b/x-pack/solutions/security/plugins/session_view/public/hooks/use_eui_theme.ts index a62cab176657b..6c43c4ad1e6b1 100644 --- a/x-pack/solutions/security/plugins/session_view/public/hooks/use_eui_theme.ts +++ b/x-pack/solutions/security/plugins/session_view/public/hooks/use_eui_theme.ts @@ -5,14 +5,12 @@ * 2.0. */ -import { shade, useEuiTheme as useEuiThemeHook } from '@elastic/eui'; -import { euiLightVars, euiDarkVars } from '@kbn/ui-theme'; +import { useEuiTheme as useEuiThemeHook } from '@elastic/eui'; +import { euiLightVars, euiDarkVars } from '@kbn/ui-theme'; // TODO: Borealis migration - replace to use vars from useEuiTheme? import { useMemo } from 'react'; type EuiThemeProps = Parameters; type ExtraEuiVars = { - // eslint-disable-next-line @typescript-eslint/naming-convention - euiColorVis6_asText: string; buttonsBackgroundNormalDefaultPrimary: string; terminalOutputBackground: string; terminalOutputMarkerAccent: string; @@ -29,14 +27,12 @@ export const useEuiTheme = (...props: EuiThemeProps): EuiThemeReturn => { const euiThemeHook = useEuiThemeHook(...props); const euiVars = useMemo(() => { - const themeVars = euiThemeHook.colorMode === 'DARK' ? euiDarkVars : euiLightVars; + const themeVars = euiThemeHook.colorMode === 'DARK' ? euiDarkVars : euiLightVars; // TODO: Borealis migration - check if euiLightVars and euiDarkVars are still available in Borialis const extraEuiVars: ExtraEuiVars = { - // eslint-disable-next-line @typescript-eslint/naming-convention - euiColorVis6_asText: shade(themeVars.euiColorVis6, 0.335), - buttonsBackgroundNormalDefaultPrimary: '#006DE4', + buttonsBackgroundNormalDefaultPrimary: '#006DE4', // TODO: Borealis migration - replace with proper color token // Terminal Output Colors don't change with the theme - terminalOutputBackground: '#1d1e23', + terminalOutputBackground: '#1d1e23', // TODO: Borealis migration - replace with proper color token terminalOutputMarkerAccent: euiLightVars.euiColorAccent, terminalOutputMarkerWarning: euiDarkVars.euiColorWarning, terminalOutputSliderBackground: euiLightVars.euiColorDarkestShade, diff --git a/x-pack/solutions/security/plugins/threat_intelligence/public/mocks/mock_security_context.tsx b/x-pack/solutions/security/plugins/threat_intelligence/public/mocks/mock_security_context.tsx index 4e1ecf0bbe885..14de05525b848 100644 --- a/x-pack/solutions/security/plugins/threat_intelligence/public/mocks/mock_security_context.tsx +++ b/x-pack/solutions/security/plugins/threat_intelligence/public/mocks/mock_security_context.tsx @@ -43,6 +43,7 @@ export const getSecuritySolutionContextMock = (): SecuritySolutionPluginContext ({ dataProviders, from, to }) => () => new Promise((resolve) => window.alert('investigate in timeline')), + hasAccessToTimeline: true, SiemSearchBar: () =>
mock siem search
, diff --git a/x-pack/solutions/security/plugins/threat_intelligence/public/mocks/test_providers.tsx b/x-pack/solutions/security/plugins/threat_intelligence/public/mocks/test_providers.tsx index c56ebb122129a..29f48c0e15df7 100644 --- a/x-pack/solutions/security/plugins/threat_intelligence/public/mocks/test_providers.tsx +++ b/x-pack/solutions/security/plugins/threat_intelligence/public/mocks/test_providers.tsx @@ -138,13 +138,26 @@ export const mockedServices = { }, }; -export const TestProvidersComponent: FC> = ({ children }) => ( +interface TestProvidersProps { + securityContextOverrides?: Partial; +} + +export const TestProvidersComponent: FC> = ({ + children, + securityContextOverrides, +}) => ( - + diff --git a/x-pack/solutions/security/plugins/threat_intelligence/public/modules/indicators/components/table/table.tsx b/x-pack/solutions/security/plugins/threat_intelligence/public/modules/indicators/components/table/table.tsx index 2fc5c93739d4d..b4578d4423478 100644 --- a/x-pack/solutions/security/plugins/threat_intelligence/public/modules/indicators/components/table/table.tsx +++ b/x-pack/solutions/security/plugins/threat_intelligence/public/modules/indicators/components/table/table.tsx @@ -36,6 +36,9 @@ import { useFieldTypes } from '../../../../hooks/use_field_types'; import { getFieldSchema } from '../../utils/get_field_schema'; import { Pagination } from '../../services/fetch_indicators'; import { TABLE_TEST_ID, TABLE_UPDATE_PROGRESS_TEST_ID } from './test_ids'; +import { useSecurityContext } from '../../../../hooks/use_security_context'; + +const actionsColumnIconWidth = 28; export interface IndicatorsTableProps { indicators: Indicator[]; @@ -70,6 +73,8 @@ export const IndicatorsTable: VFC = ({ browserFields, columnSettings: { columns, columnVisibility, handleResetColumns, handleToggleColumn, sorting }, }) => { + const securitySolutionContext = useSecurityContext(); + const [expanded, setExpanded] = useState(); const fieldTypes = useFieldTypes(); @@ -96,7 +101,9 @@ export const IndicatorsTable: VFC = ({ () => [ { id: 'Actions', - width: 84, + width: securitySolutionContext?.hasAccessToTimeline + ? 3 * actionsColumnIconWidth + : 2 * actionsColumnIconWidth, headerCellRender: () => ( = ({ rowCellRender: renderCellValue, }, ], - [renderCellValue] + [renderCellValue, securitySolutionContext?.hasAccessToTimeline] ); const mappedColumns = useMemo( diff --git a/x-pack/solutions/security/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline.test.tsx b/x-pack/solutions/security/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline.test.tsx index a5d8ae3e3996d..2372c8803b08a 100644 --- a/x-pack/solutions/security/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline.test.tsx +++ b/x-pack/solutions/security/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline.test.tsx @@ -153,4 +153,17 @@ describe(' ', () => { ); expect(container).toBeEmptyDOMElement(); }); + + it('should render empty when the user does not have access to timeline', () => { + const mockField: string = 'threat.indicator.ip'; + const mockData: Indicator = generateMockIndicator(); + + const { container } = render( + + + + ); + + expect(container).toBeEmptyDOMElement(); + }); }); diff --git a/x-pack/solutions/security/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline.tsx b/x-pack/solutions/security/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline.tsx index 214a6472bb600..b964273118d04 100644 --- a/x-pack/solutions/security/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline.tsx +++ b/x-pack/solutions/security/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline.tsx @@ -19,6 +19,7 @@ import { generateDataProvider } from '../utils/data_provider'; import { fieldAndValueValid, getIndicatorFieldAndValue } from '../../indicators/utils/field_value'; import { Indicator } from '../../../../common/types/indicator'; import { useKibana } from '../../../hooks/use_kibana'; +import { useSecurityContext } from '../../../hooks/use_security_context'; import { useStyles } from './styles'; import { useAddToTimeline } from '../hooks/use_add_to_timeline'; import { TITLE } from './translations'; @@ -62,9 +63,10 @@ export const AddToTimelineButtonIcon: VFC = ({ }) => { const addToTimelineButton = useKibana().services.timelines.getHoverActions().getAddToTimelineButton; + const securitySolutionContext = useSecurityContext(); const { addToTimelineProps } = useAddToTimeline({ indicator: data, field }); - if (!addToTimelineProps) { + if (!securitySolutionContext?.hasAccessToTimeline || !addToTimelineProps) { return null; } @@ -91,7 +93,7 @@ export const AddToTimelineButtonEmpty: VFC = ({ 'data-test-subj': dataTestSubj, }) => { const styles = useStyles(); - + const securitySolutionContext = useSecurityContext(); const buttonRef = useRef(null); const { timelines, analytics, i18n: i18nStart, theme } = useKibana().services; @@ -101,7 +103,7 @@ export const AddToTimelineButtonEmpty: VFC = ({ const { key, value } = typeof data === 'string' ? { key: field, value: data } : getIndicatorFieldAndValue(data, field); - if (!fieldAndValueValid(key, value)) { + if (!securitySolutionContext?.hasAccessToTimeline || !fieldAndValueValid(key, value)) { return null; } @@ -152,7 +154,7 @@ export const AddToTimelineContextMenu: VFC = ({ 'data-test-subj': dataTestSubj, }) => { const styles = useStyles(); - + const securitySolutionContext = useSecurityContext(); const contextMenuRef = useRef(null); const { timelines, analytics, i18n: i18nStart, theme } = useKibana().services; @@ -163,7 +165,7 @@ export const AddToTimelineContextMenu: VFC = ({ const { key, value } = typeof data === 'string' ? { key: field, value: data } : getIndicatorFieldAndValue(data, field); - if (!fieldAndValueValid(key, value)) { + if (!securitySolutionContext?.hasAccessToTimeline || !fieldAndValueValid(key, value)) { return null; } @@ -213,9 +215,10 @@ export const AddToTimelineCellAction: VFC = ({ }) => { const addToTimelineButton = useKibana().services.timelines.getHoverActions().getAddToTimelineButton; + const securitySolutionContext = useSecurityContext(); const { addToTimelineProps } = useAddToTimeline({ indicator: data, field }); - if (!addToTimelineProps) { + if (!securitySolutionContext?.hasAccessToTimeline || !addToTimelineProps) { return null; } addToTimelineProps.Component = Component; diff --git a/x-pack/solutions/security/plugins/threat_intelligence/public/modules/timeline/components/investigate_in_timeline.test.tsx b/x-pack/solutions/security/plugins/threat_intelligence/public/modules/timeline/components/investigate_in_timeline.test.tsx index 1fcbb3d6c6c49..d7419a475d9a2 100644 --- a/x-pack/solutions/security/plugins/threat_intelligence/public/modules/timeline/components/investigate_in_timeline.test.tsx +++ b/x-pack/solutions/security/plugins/threat_intelligence/public/modules/timeline/components/investigate_in_timeline.test.tsx @@ -74,4 +74,15 @@ describe(' { + const mockData: Indicator = generateMockUrlIndicator(); + + const { container } = render( + + + + ); + expect(container).toBeEmptyDOMElement(); + }); }); diff --git a/x-pack/solutions/security/plugins/threat_intelligence/public/modules/timeline/components/investigate_in_timeline.tsx b/x-pack/solutions/security/plugins/threat_intelligence/public/modules/timeline/components/investigate_in_timeline.tsx index e894fa99c9e6c..81678c7632b8b 100644 --- a/x-pack/solutions/security/plugins/threat_intelligence/public/modules/timeline/components/investigate_in_timeline.tsx +++ b/x-pack/solutions/security/plugins/threat_intelligence/public/modules/timeline/components/investigate_in_timeline.tsx @@ -9,6 +9,7 @@ import React, { VFC } from 'react'; import { EuiButtonIcon, EuiContextMenuItem, EuiToolTip } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { useInvestigateInTimeline } from '../hooks/use_investigate_in_timeline'; +import { useSecurityContext } from '../../../hooks/use_security_context'; import { Indicator } from '../../../../common/types/indicator'; import { BUTTON_ICON_LABEL } from './translations'; @@ -41,7 +42,9 @@ export const InvestigateInTimelineContextMenu: VFC = 'data-test-subj': dataTestSub, }) => { const { investigateInTimelineFn } = useInvestigateInTimeline({ indicator: data }); - if (!investigateInTimelineFn) { + const securitySolutionContext = useSecurityContext(); + + if (!securitySolutionContext?.hasAccessToTimeline || !investigateInTimelineFn) { return null; } @@ -77,7 +80,9 @@ export const InvestigateInTimelineButtonIcon: VFC = 'data-test-subj': dataTestSub, }) => { const { investigateInTimelineFn } = useInvestigateInTimeline({ indicator: data }); - if (!investigateInTimelineFn) { + const securitySolutionContext = useSecurityContext(); + + if (!securitySolutionContext?.hasAccessToTimeline || !investigateInTimelineFn) { return null; } diff --git a/x-pack/solutions/security/plugins/threat_intelligence/public/types.ts b/x-pack/solutions/security/plugins/threat_intelligence/public/types.ts index deffb286068fa..7c7f012be63b7 100644 --- a/x-pack/solutions/security/plugins/threat_intelligence/public/types.ts +++ b/x-pack/solutions/security/plugins/threat_intelligence/public/types.ts @@ -130,6 +130,11 @@ export interface SecuritySolutionPluginContext { to, }: UseInvestigateInTimelineProps) => () => Promise; + /** + * Whether the current user has access to timeline + */ + hasAccessToTimeline: boolean; + useQuery: () => Query; useFilters: () => Filter[]; diff --git a/x-pack/test/accessibility/apps/group1/dashboard_panel_options.ts b/x-pack/test/accessibility/apps/group1/dashboard_panel_options.ts index 9ef299ca1cf2d..0be6a6d48ea46 100644 --- a/x-pack/test/accessibility/apps/group1/dashboard_panel_options.ts +++ b/x-pack/test/accessibility/apps/group1/dashboard_panel_options.ts @@ -132,7 +132,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('dashboard panel - save to library', async () => { - await dashboardPanelActions.legacySaveToLibrary('', title); + await dashboardPanelActions.saveToLibrary('', title); await a11y.testAppSnapshot(); await testSubjects.click('saveCancelButton'); }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/delete.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/delete.ts index 9a2f0777c6403..3d3f2329288a6 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/delete.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/delete.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import moment from 'moment'; import { asyncForEach } from '@kbn/std'; -import { GetResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { GetResponse } from '@elastic/elasticsearch/lib/api/types'; import { UserAtSpaceScenarios } from '../../../../scenarios'; import { getTestRuleData, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/index.ts index d7fe17b4aa1f5..11b62918abe99 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/index.ts @@ -17,5 +17,6 @@ export default function backfillTests({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./delete')); loadTestFile(require.resolve('./delete_rule')); loadTestFile(require.resolve('./task_runner')); + loadTestFile(require.resolve('./task_runner_with_actions')); }); } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/schedule.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/schedule.ts index d2fdb7f4365f4..051103e7804b9 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/schedule.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/schedule.ts @@ -13,14 +13,9 @@ import { get } from 'lodash'; import { AD_HOC_RUN_SAVED_OBJECT_TYPE } from '@kbn/alerting-plugin/server/saved_objects'; import { asyncForEach } from '../../../../../../functional/services/transform/api'; import { UserAtSpaceScenarios } from '../../../../scenarios'; -import { - checkAAD, - getTestRuleData, - getUrlPrefix, - ObjectRemover, - TaskManagerDoc, -} from '../../../../../common/lib'; +import { checkAAD, getTestRuleData, getUrlPrefix, ObjectRemover } from '../../../../../common/lib'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { TEST_ACTIONS_INDEX, getScheduledTask } from './test_utils'; // eslint-disable-next-line import/no-default-export export default function scheduleBackfillTests({ getService }: FtrProviderContext) { @@ -36,6 +31,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext await asyncForEach(backfillIds, async ({ id, spaceId }: { id: string; spaceId: string }) => { await supertest .delete(`${getUrlPrefix(spaceId)}/internal/alerting/rules/backfill/${id}`) + .set('x-elastic-internal-origin', 'xxx') .set('kbn-xsrf', 'foo'); }); backfillIds = []; @@ -50,16 +46,13 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext return result._source; } - async function getScheduledTask(id: string): Promise { - const scheduledTask = await es.get({ - id: `task:${id}`, - index: '.kibana_task_manager', - }); - return scheduledTask._source!; - } - function getRule(overwrites = {}) { - return getTestRuleData({ + return { + name: 'abc', + enabled: true, + tags: ['foo'], + consumer: 'alertsFixture', + actions: [], rule_type_id: 'test.patternFiringAutoRecoverFalse', params: { pattern: { @@ -68,7 +61,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext }, schedule: { interval: '12h' }, ...overwrites, - }); + }; } function getLifecycleRule(overwrites = {}) { @@ -151,6 +144,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext // schedule backfill for both rules as current user const response = await supertestWithoutAuth .post(`${getUrlPrefix(apiOptions.spaceId)}/internal/alerting/rules/backfill/_schedule`) + .set('x-elastic-internal-origin', 'xxx') .set('kbn-xsrf', 'foo') .auth(apiOptions.username, apiOptions.password) .send([ @@ -283,7 +277,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext expect(adHocRunSO2.references).to.eql([{ id: ruleId2, name: 'rule', type: 'alert' }]); // check that the task was scheduled correctly - const taskRecord1 = await getScheduledTask(result[0].id); + const taskRecord1 = await getScheduledTask(es, result[0].id); expect(taskRecord1.type).to.eql('task'); expect(taskRecord1.task.taskType).to.eql('ad_hoc_run-backfill'); expect(taskRecord1.task.timeoutOverride).to.eql('10s'); @@ -292,7 +286,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext adHocRunParamsId: result[0].id, spaceId: space.id, }); - const taskRecord2 = await getScheduledTask(result[1].id); + const taskRecord2 = await getScheduledTask(es, result[1].id); expect(taskRecord2.type).to.eql('task'); expect(taskRecord2.task.taskType).to.eql('ad_hoc_run-backfill'); expect(taskRecord2.task.timeoutOverride).to.eql('10s'); @@ -339,6 +333,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext // schedule 3 backfill jobs for rule as current user const response = await supertestWithoutAuth .post(`${getUrlPrefix(apiOptions.spaceId)}/internal/alerting/rules/backfill/_schedule`) + .set('x-elastic-internal-origin', 'xxx') .set('kbn-xsrf', 'foo') .auth(apiOptions.username, apiOptions.password) .send([ @@ -514,7 +509,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext expect(adHocRunSO3.references).to.eql([{ id: ruleId, name: 'rule', type: 'alert' }]); // check that the task was scheduled correctly - const taskRecord1 = await getScheduledTask(result[0].id); + const taskRecord1 = await getScheduledTask(es, result[0].id); expect(taskRecord1.type).to.eql('task'); expect(taskRecord1.task.taskType).to.eql('ad_hoc_run-backfill'); expect(taskRecord1.task.timeoutOverride).to.eql('10s'); @@ -523,7 +518,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext adHocRunParamsId: result[0].id, spaceId: space.id, }); - const taskRecord2 = await getScheduledTask(result[1].id); + const taskRecord2 = await getScheduledTask(es, result[1].id); expect(taskRecord2.type).to.eql('task'); expect(taskRecord2.task.taskType).to.eql('ad_hoc_run-backfill'); expect(taskRecord2.task.timeoutOverride).to.eql('10s'); @@ -532,7 +527,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext adHocRunParamsId: result[1].id, spaceId: space.id, }); - const taskRecord3 = await getScheduledTask(result[2].id); + const taskRecord3 = await getScheduledTask(es, result[2].id); expect(taskRecord3.type).to.eql('task'); expect(taskRecord3.task.taskType).to.eql('ad_hoc_run-backfill'); expect(taskRecord3.task.timeoutOverride).to.eql('10s'); @@ -572,6 +567,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext // invalid start time const response1 = await supertestWithoutAuth .post(`${getUrlPrefix(apiOptions.spaceId)}/internal/alerting/rules/backfill/_schedule`) + .set('x-elastic-internal-origin', 'xxx') .set('kbn-xsrf', 'foo') .auth(apiOptions.username, apiOptions.password) .send([{ rule_id: 'abc', start: 'foo' }]); @@ -579,6 +575,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext // invalid end time const response2 = await supertestWithoutAuth .post(`${getUrlPrefix(apiOptions.spaceId)}/internal/alerting/rules/backfill/_schedule`) + .set('x-elastic-internal-origin', 'xxx') .set('kbn-xsrf', 'foo') .auth(apiOptions.username, apiOptions.password) .send([ @@ -593,6 +590,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext const time = moment().utc().startOf('day').subtract(7, 'days').toISOString(); const response3 = await supertestWithoutAuth .post(`${getUrlPrefix(apiOptions.spaceId)}/internal/alerting/rules/backfill/_schedule`) + .set('x-elastic-internal-origin', 'xxx') .set('kbn-xsrf', 'foo') .auth(apiOptions.username, apiOptions.password) .send([{ rule_id: 'abc', start: time, end: time }]); @@ -600,6 +598,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext // end time is before start time const response4 = await supertestWithoutAuth .post(`${getUrlPrefix(apiOptions.spaceId)}/internal/alerting/rules/backfill/_schedule`) + .set('x-elastic-internal-origin', 'xxx') .set('kbn-xsrf', 'foo') .auth(apiOptions.username, apiOptions.password) .send([ @@ -613,6 +612,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext // start time is too far in the past const response5 = await supertestWithoutAuth .post(`${getUrlPrefix(apiOptions.spaceId)}/internal/alerting/rules/backfill/_schedule`) + .set('x-elastic-internal-origin', 'xxx') .set('kbn-xsrf', 'foo') .auth(apiOptions.username, apiOptions.password) .send([{ rule_id: 'abc', start: '2023-04-30T00:00:00.000Z' }]); @@ -620,6 +620,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext // start time is in the future const response6 = await supertestWithoutAuth .post(`${getUrlPrefix(apiOptions.spaceId)}/internal/alerting/rules/backfill/_schedule`) + .set('x-elastic-internal-origin', 'xxx') .set('kbn-xsrf', 'foo') .auth(apiOptions.username, apiOptions.password) .send([ @@ -629,6 +630,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext // end time is in the future const response7 = await supertestWithoutAuth .post(`${getUrlPrefix(apiOptions.spaceId)}/internal/alerting/rules/backfill/_schedule`) + .set('x-elastic-internal-origin', 'xxx') .set('kbn-xsrf', 'foo') .auth(apiOptions.username, apiOptions.password) .send([ @@ -715,6 +717,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext // schedule backfill for non-existent rule const response = await supertestWithoutAuth .post(`${getUrlPrefix(apiOptions.spaceId)}/internal/alerting/rules/backfill/_schedule`) + .set('x-elastic-internal-origin', 'xxx') .set('kbn-xsrf', 'foo') .auth(apiOptions.username, apiOptions.password) .send([ @@ -814,6 +817,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext // schedule backfill as current user const response = await supertestWithoutAuth .post(`${getUrlPrefix(apiOptions.spaceId)}/internal/alerting/rules/backfill/_schedule`) + .set('x-elastic-internal-origin', 'xxx') .set('kbn-xsrf', 'foo') .auth(apiOptions.username, apiOptions.password) .send([ @@ -1019,7 +1023,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext expect(adHocRunSO3.references).to.eql([{ id: ruleId1, name: 'rule', type: 'alert' }]); // check that the task was scheduled correctly - const taskRecord1 = await getScheduledTask(result[0].id); + const taskRecord1 = await getScheduledTask(es, result[0].id); expect(taskRecord1.type).to.eql('task'); expect(taskRecord1.task.taskType).to.eql('ad_hoc_run-backfill'); expect(taskRecord1.task.timeoutOverride).to.eql('10s'); @@ -1028,7 +1032,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext adHocRunParamsId: result[0].id, spaceId: space.id, }); - const taskRecord2 = await getScheduledTask(result[1].id); + const taskRecord2 = await getScheduledTask(es, result[1].id); expect(taskRecord2.type).to.eql('task'); expect(taskRecord2.task.taskType).to.eql('ad_hoc_run-backfill'); expect(taskRecord2.task.timeoutOverride).to.eql('10s'); @@ -1037,7 +1041,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext adHocRunParamsId: result[1].id, spaceId: space.id, }); - const taskRecord3 = await getScheduledTask(result[5].id); + const taskRecord3 = await getScheduledTask(es, result[5].id); expect(taskRecord3.type).to.eql('task'); expect(taskRecord3.task.taskType).to.eql('ad_hoc_run-backfill'); expect(taskRecord3.task.timeoutOverride).to.eql('10s'); @@ -1071,6 +1075,267 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); } }); + + it('should handle schedule request where rule has supported and unsupported actions', async () => { + // create a connector + const cresponse = await supertest + .post(`${getUrlPrefix(apiOptions.spaceId)}/api/actions/connector`) + .set('kbn-xsrf', 'foo') + .send({ + name: 'An index connector', + connector_type_id: '.index', + config: { + index: TEST_ACTIONS_INDEX, + refresh: true, + }, + secrets: {}, + }) + .expect(200); + const connectorId = cresponse.body.id; + objectRemover.add(apiOptions.spaceId, connectorId, 'connector', 'actions'); + + const start = moment().utc().startOf('day').subtract(14, 'days').toISOString(); + const end = moment().utc().startOf('day').subtract(5, 'days').toISOString(); + // create 2 rules + const rresponse1 = await supertest + .post(`${getUrlPrefix(apiOptions.spaceId)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send( + getRule({ + actions: [ + { + group: 'default', + id: connectorId, + uuid: '111-111', + params: { documents: [{ alertUuid: '{{alert.uuid}}' }] }, + frequency: { notify_when: 'onActiveAlert', throttle: null, summary: true }, + }, + { + group: 'default', + id: connectorId, + uuid: '222-222', + params: { documents: [{ alertUuid: '{{alert.uuid}}' }] }, + frequency: { + notify_when: 'onActionGroupChange', + throttle: null, + summary: true, + }, + }, + ], + }) + ) + .expect(200); + const ruleId1 = rresponse1.body.id; + objectRemover.add(apiOptions.spaceId, ruleId1, 'rule', 'alerting'); + + const rresponse2 = await supertest + .post(`${getUrlPrefix(apiOptions.spaceId)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send( + getRule({ + actions: [ + { + group: 'default', + id: connectorId, + uuid: '333-333', + params: { documents: [{ alertUuid: '{{alert.uuid}}' }] }, + frequency: { notify_when: 'onActiveAlert', throttle: null, summary: false }, + }, + ], + }) + ) + .expect(200); + const ruleId2 = rresponse2.body.id; + objectRemover.add(apiOptions.spaceId, ruleId2, 'rule', 'alerting'); + + // schedule backfill as current user + const response = await supertestWithoutAuth + .post(`${getUrlPrefix(apiOptions.spaceId)}/internal/alerting/rules/backfill/_schedule`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'xxx') + .auth(apiOptions.username, apiOptions.password) + .send([ + { rule_id: ruleId1, start, end, run_actions: true }, + { rule_id: ruleId2, start, end, run_actions: true }, + ]); + + switch (scenario.id) { + // User can't do anything in this space + case 'no_kibana_privileges at space1': + // User has no privileges in this space + case 'space_1_all at space2': + expect(response.statusCode).to.eql(403); + expect(response.body).to.eql({ + error: 'Forbidden', + message: `Unauthorized to find rules for any rule types`, + statusCode: 403, + }); + break; + // User has read privileges in this space + case 'global_read at space1': + expect(response.statusCode).to.eql(403); + expect(response.body.error).to.eql('Forbidden'); + expect(response.body.message).to.match( + /Unauthorized by "alertsFixture" to scheduleBackfill "[^"]+" rule/ + ); + break; + // User doesn't have access to actions + case 'space_1_all_alerts_none_actions at space1': + expect(response.statusCode).to.eql(403); + expect(response.body.error).to.eql('Forbidden'); + expect(response.body.message).to.eql('Unauthorized to get actions'); + break; + // Superuser has access to everything + case 'superuser at space1': + // User has all privileges in this space + case 'space_1_all at space1': + // User has all privileges in this space + case 'space_1_all_with_restricted_fixture at space1': + expect(response.statusCode).to.eql(200); + const result = response.body; + + expect(result.length).to.eql(2); + + // successful schedule with warning for unsupported action + expect(typeof result[0].id).to.be('string'); + backfillIds.push({ id: result[0].id, spaceId: apiOptions.spaceId }); + expect(result[0].duration).to.eql('12h'); + expect(result[0].enabled).to.eql(true); + expect(result[0].start).to.eql(start); + expect(result[0].end).to.eql(end); + expect(result[0].status).to.eql('pending'); + expect(result[0].space_id).to.eql(space.id); + expect(typeof result[0].created_at).to.be('string'); + expect(result[0].rule.actions.length).to.eql(1); + expect(result[0].rule.actions[0]).to.eql({ + actionTypeId: '.index', + group: 'default', + id: connectorId, + uuid: '111-111', + params: { documents: [{ alertUuid: '{{alert.uuid}}' }] }, + frequency: { notifyWhen: 'onActiveAlert', throttle: null, summary: true }, + }); + expect(result[0].warnings).to.eql([ + `Rule has actions that are not supported for backfill. Those actions will be skipped.`, + ]); + + let currentStart = start; + result[0].schedule.forEach((sched: any) => { + expect(sched.interval).to.eql('12h'); + expect(sched.status).to.eql('pending'); + const runAt = moment(currentStart).add(12, 'hours').toISOString(); + expect(sched.run_at).to.eql(runAt); + currentStart = runAt; + }); + + // // successful schedule + expect(typeof result[1].id).to.be('string'); + backfillIds.push({ id: result[1].id, spaceId: apiOptions.spaceId }); + expect(result[1].duration).to.eql('12h'); + expect(result[1].enabled).to.eql(true); + expect(result[1].start).to.eql(start); + expect(result[1].end).to.eql(end); + expect(result[1].status).to.eql('pending'); + expect(result[1].space_id).to.eql(space.id); + expect(typeof result[1].created_at).to.be('string'); + expect(result[1].rule.actions.length).to.eql(1); + expect(result[1].rule.actions[0]).to.eql({ + actionTypeId: '.index', + group: 'default', + id: connectorId, + uuid: '333-333', + params: { documents: [{ alertUuid: '{{alert.uuid}}' }] }, + frequency: { notifyWhen: 'onActiveAlert', throttle: null, summary: false }, + }); + expect(result[1].warnings).to.be(undefined); + + currentStart = start; + result[1].schedule.forEach((sched: any) => { + expect(sched.interval).to.eql('12h'); + expect(sched.status).to.eql('pending'); + const runAt = moment(currentStart).add(12, 'hours').toISOString(); + expect(sched.run_at).to.eql(runAt); + currentStart = runAt; + }); + + // check that the expected ad hoc run SOs were created + const adHocRunSO1 = (await getAdHocRunSO(result[0].id)) as SavedObject; + const adHocRun1: AdHocRunSO = get(adHocRunSO1, 'ad_hoc_run_params')!; + const adHocRunSO2 = (await getAdHocRunSO(result[1].id)) as SavedObject; + const adHocRun2: AdHocRunSO = get(adHocRunSO2, 'ad_hoc_run_params')!; + + expect(typeof adHocRun1.apiKeyId).to.be('string'); + expect(typeof adHocRun1.apiKeyToUse).to.be('string'); + expect(typeof adHocRun1.createdAt).to.be('string'); + expect(adHocRun1.duration).to.eql('12h'); + expect(adHocRun1.enabled).to.eql(true); + expect(adHocRun1.start).to.eql(start); + expect(adHocRun1.end).to.eql(end); + expect(adHocRun1.status).to.eql('pending'); + expect(adHocRun1.spaceId).to.eql(space.id); + + currentStart = start; + adHocRun1.schedule.forEach((sched: any) => { + expect(sched.interval).to.eql('12h'); + expect(sched.status).to.eql('pending'); + const runAt = moment(currentStart).add(12, 'hours').toISOString(); + expect(sched.runAt).to.eql(runAt); + currentStart = runAt; + }); + + expect(typeof adHocRun2.apiKeyId).to.be('string'); + expect(typeof adHocRun2.apiKeyToUse).to.be('string'); + expect(typeof adHocRun2.createdAt).to.be('string'); + expect(adHocRun2.duration).to.eql('12h'); + expect(adHocRun2.enabled).to.eql(true); + expect(adHocRun2.start).to.eql(start); + expect(adHocRun2.end).to.eql(end); + expect(adHocRun2.status).to.eql('pending'); + expect(adHocRun2.spaceId).to.eql(space.id); + + currentStart = start; + adHocRun2.schedule.forEach((sched: any) => { + expect(sched.interval).to.eql('12h'); + expect(sched.status).to.eql('pending'); + const runAt = moment(currentStart).add(12, 'hours').toISOString(); + expect(sched.runAt).to.eql(runAt); + currentStart = runAt; + }); + + // check references are stored correctly + expect(adHocRunSO1.references).to.eql([ + { id: ruleId1, name: 'rule', type: 'alert' }, + { id: connectorId, name: 'action_0', type: 'action' }, + ]); + expect(adHocRunSO2.references).to.eql([ + { id: ruleId2, name: 'rule', type: 'alert' }, + { id: connectorId, name: 'action_0', type: 'action' }, + ]); + + // check that the task was scheduled correctly + const taskRecord1 = await getScheduledTask(es, result[0].id); + expect(taskRecord1.type).to.eql('task'); + expect(taskRecord1.task.taskType).to.eql('ad_hoc_run-backfill'); + expect(taskRecord1.task.timeoutOverride).to.eql('10s'); + expect(taskRecord1.task.enabled).to.eql(true); + expect(JSON.parse(taskRecord1.task.params)).to.eql({ + adHocRunParamsId: result[0].id, + spaceId: space.id, + }); + const taskRecord2 = await getScheduledTask(es, result[1].id); + expect(taskRecord2.type).to.eql('task'); + expect(taskRecord2.task.taskType).to.eql('ad_hoc_run-backfill'); + expect(taskRecord2.task.timeoutOverride).to.eql('10s'); + expect(taskRecord2.task.enabled).to.eql(true); + expect(JSON.parse(taskRecord2.task.params)).to.eql({ + adHocRunParamsId: result[1].id, + spaceId: space.id, + }); + break; + default: + throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); + } + }); }); } }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/task_runner.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/task_runner.ts index 2083a79c0d0f5..0bd46289c416f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/task_runner.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/task_runner.ts @@ -7,7 +7,6 @@ import expect from '@kbn/expect'; import moment from 'moment'; -import { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { SecurityAlert } from '@kbn/alerts-as-data-utils'; import { ALERT_LAST_DETECTED, @@ -33,27 +32,23 @@ import { RULE_SAVED_OBJECT_TYPE, } from '@kbn/alerting-plugin/server/saved_objects'; import { ALERT_ORIGINAL_TIME } from '@kbn/security-solution-plugin/common/field_maps/field_names'; -import { - createEsDocument, - DOCUMENT_REFERENCE, - DOCUMENT_SOURCE, -} from '../../../../../spaces_only/tests/alerting/create_test_data'; -import { asyncForEach } from '../../../../../../functional/services/transform/api'; +import { DOCUMENT_SOURCE } from '../../../../../spaces_only/tests/alerting/create_test_data'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; import { SuperuserAtSpace1 } from '../../../../scenarios'; +import { getTestRuleData, getUrlPrefix, ObjectRemover } from '../../../../../common/lib'; import { - getEventLog, - getTestRuleData, - getUrlPrefix, - ObjectRemover, - TaskManagerDoc, -} from '../../../../../common/lib'; + getScheduledTask, + indexTestDocs, + queryForAlertDocs, + searchScheduledTask, + testDocTimestamps, + waitForEventLogDocs, +} from './test_utils'; // eslint-disable-next-line import/no-default-export export default function createBackfillTaskRunnerTests({ getService }: FtrProviderContext) { const es = getService('es'); const retry = getService('retry'); - const log = getService('log'); const esTestIndexTool = new ESTestIndexTool(es, retry); const supertestWithoutAuth = getService('supertestWithoutAuth'); const supertest = getService('supertest'); @@ -61,31 +56,6 @@ export default function createBackfillTaskRunnerTests({ getService }: FtrProvide const alertsAsDataIndex = '.alerts-security.alerts-space1'; const timestampPattern = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/; - const originalDocTimestamps = [ - // before first backfill run - moment().utc().subtract(14, 'days').toISOString(), - - // backfill execution set 1 - moment().utc().startOf('day').subtract(13, 'days').add(10, 'minutes').toISOString(), - moment().utc().startOf('day').subtract(13, 'days').add(11, 'minutes').toISOString(), - moment().utc().startOf('day').subtract(13, 'days').add(12, 'minutes').toISOString(), - - // backfill execution set 2 - moment().utc().startOf('day').subtract(12, 'days').add(20, 'minutes').toISOString(), - - // backfill execution set 3 - moment().utc().startOf('day').subtract(11, 'days').add(30, 'minutes').toISOString(), - moment().utc().startOf('day').subtract(11, 'days').add(31, 'minutes').toISOString(), - moment().utc().startOf('day').subtract(11, 'days').add(32, 'minutes').toISOString(), - moment().utc().startOf('day').subtract(11, 'days').add(33, 'minutes').toISOString(), - moment().utc().startOf('day').subtract(11, 'days').add(34, 'minutes').toISOString(), - - // backfill execution set 4 purposely left empty - - // after last backfill - moment().utc().startOf('day').subtract(9, 'days').add(40, 'minutes').toISOString(), - moment().utc().startOf('day').subtract(9, 'days').add(41, 'minutes').toISOString(), - ]; describe('ad hoc backfill task', () => { beforeEach(async () => { @@ -113,7 +83,7 @@ export default function createBackfillTaskRunnerTests({ getService }: FtrProvide const spaceId = SuperuserAtSpace1.space.id; // Index documents - await indexTestDocs(); + await indexTestDocs(es, esTestIndexTool); // Create siem.queryRule const response1 = await supertestWithoutAuth @@ -165,8 +135,8 @@ export default function createBackfillTaskRunnerTests({ getService }: FtrProvide const ruleId = response1.body.id; objectRemover.add(spaceId, ruleId, 'rule', 'alerting'); - const start = moment(originalDocTimestamps[1]).utc().startOf('day').toISOString(); - const end = moment(originalDocTimestamps[11]).utc().startOf('day').toISOString(); + const start = moment(testDocTimestamps[1]).utc().startOf('day').toISOString(); + const end = moment(testDocTimestamps[11]).utc().startOf('day').toISOString(); // Schedule backfill for this rule const response2 = await supertestWithoutAuth @@ -176,9 +146,6 @@ export default function createBackfillTaskRunnerTests({ getService }: FtrProvide .send([{ rule_id: ruleId, start, end }]) .expect(200); - log.info(`originalDocTimestamps ${JSON.stringify(originalDocTimestamps)}`); - log.info(`scheduledBackfill ${JSON.stringify(response2.body)}`); - const scheduleResult = response2.body; expect(scheduleResult.length).to.eql(1); @@ -196,7 +163,7 @@ export default function createBackfillTaskRunnerTests({ getService }: FtrProvide const backfillId = scheduleResult[0].id; // check that the task was scheduled correctly - const taskRecord = await getScheduledTask(backfillId); + const taskRecord = await getScheduledTask(es, backfillId); expect(taskRecord.type).to.eql('task'); expect(taskRecord.task.taskType).to.eql('ad_hoc_run-backfill'); expect(taskRecord.task.timeoutOverride).to.eql('5m'); @@ -208,6 +175,8 @@ export default function createBackfillTaskRunnerTests({ getService }: FtrProvide // get the execute-backfill events const events: IValidatedEvent[] = await waitForEventLogDocs( + retry, + getService, backfillId, spaceId, new Map([['execute-backfill', { equal: 4 }]]) @@ -284,7 +253,7 @@ export default function createBackfillTaskRunnerTests({ getService }: FtrProvide ); // query for alert docs - const alertDocs = await queryForAlertDocs(); + const alertDocs = await queryForAlertDocs(es, alertsAsDataIndex); expect(alertDocs.length).to.eql(9); // each alert doc should have these fields @@ -320,9 +289,9 @@ export default function createBackfillTaskRunnerTests({ getService }: FtrProvide ); } - expect(alertDocsBackfill1[0]._source![ALERT_ORIGINAL_TIME]).to.eql(originalDocTimestamps[1]); - expect(alertDocsBackfill1[1]._source![ALERT_ORIGINAL_TIME]).to.eql(originalDocTimestamps[2]); - expect(alertDocsBackfill1[2]._source![ALERT_ORIGINAL_TIME]).to.eql(originalDocTimestamps[3]); + expect(alertDocsBackfill1[0]._source![ALERT_ORIGINAL_TIME]).to.eql(testDocTimestamps[1]); + expect(alertDocsBackfill1[1]._source![ALERT_ORIGINAL_TIME]).to.eql(testDocTimestamps[2]); + expect(alertDocsBackfill1[2]._source![ALERT_ORIGINAL_TIME]).to.eql(testDocTimestamps[3]); // backfill run 2 alerts const alertDocsBackfill2 = alertDocs.filter( @@ -342,7 +311,7 @@ export default function createBackfillTaskRunnerTests({ getService }: FtrProvide ); } - expect(alertDocsBackfill2[0]._source![ALERT_ORIGINAL_TIME]).to.eql(originalDocTimestamps[4]); + expect(alertDocsBackfill2[0]._source![ALERT_ORIGINAL_TIME]).to.eql(testDocTimestamps[4]); // backfill run 3 alerts const alertDocsBackfill3 = alertDocs.filter( @@ -362,11 +331,11 @@ export default function createBackfillTaskRunnerTests({ getService }: FtrProvide ); } - expect(alertDocsBackfill3[0]._source![ALERT_ORIGINAL_TIME]).to.eql(originalDocTimestamps[5]); - expect(alertDocsBackfill3[1]._source![ALERT_ORIGINAL_TIME]).to.eql(originalDocTimestamps[6]); - expect(alertDocsBackfill3[2]._source![ALERT_ORIGINAL_TIME]).to.eql(originalDocTimestamps[7]); - expect(alertDocsBackfill3[3]._source![ALERT_ORIGINAL_TIME]).to.eql(originalDocTimestamps[8]); - expect(alertDocsBackfill3[4]._source![ALERT_ORIGINAL_TIME]).to.eql(originalDocTimestamps[9]); + expect(alertDocsBackfill3[0]._source![ALERT_ORIGINAL_TIME]).to.eql(testDocTimestamps[5]); + expect(alertDocsBackfill3[1]._source![ALERT_ORIGINAL_TIME]).to.eql(testDocTimestamps[6]); + expect(alertDocsBackfill3[2]._source![ALERT_ORIGINAL_TIME]).to.eql(testDocTimestamps[7]); + expect(alertDocsBackfill3[3]._source![ALERT_ORIGINAL_TIME]).to.eql(testDocTimestamps[8]); + expect(alertDocsBackfill3[4]._source![ALERT_ORIGINAL_TIME]).to.eql(testDocTimestamps[9]); // backfill run 4 alerts const alertDocsBackfill4 = alertDocs.filter( @@ -375,7 +344,7 @@ export default function createBackfillTaskRunnerTests({ getService }: FtrProvide expect(alertDocsBackfill4.length).to.eql(0); // task should have been deleted after backfill runs have finished - const numHits = await searchScheduledTask(backfillId); + const numHits = await searchScheduledTask(es, backfillId); expect(numHits).to.eql(0); }); @@ -425,7 +394,7 @@ export default function createBackfillTaskRunnerTests({ getService }: FtrProvide const backfillId = scheduleResult[0].id; // check that the task was scheduled correctly - const taskRecord = await getScheduledTask(backfillId); + const taskRecord = await getScheduledTask(es, backfillId); expect(taskRecord.type).to.eql('task'); expect(taskRecord.task.taskType).to.eql('ad_hoc_run-backfill'); expect(taskRecord.task.timeoutOverride).to.eql('10s'); @@ -437,6 +406,8 @@ export default function createBackfillTaskRunnerTests({ getService }: FtrProvide // get the execute-timeout and execute-backfill events const events: IValidatedEvent[] = await waitForEventLogDocs( + retry, + getService, backfillId, spaceId, new Map([ @@ -515,7 +486,7 @@ export default function createBackfillTaskRunnerTests({ getService }: FtrProvide } // task should have been deleted after backfill runs have finished - const numHits = await searchScheduledTask(backfillId); + const numHits = await searchScheduledTask(es, backfillId); expect(numHits).to.eql(0); }); @@ -567,7 +538,7 @@ export default function createBackfillTaskRunnerTests({ getService }: FtrProvide const backfillId = scheduleResult[0].id; // check that the task was scheduled correctly - const taskRecord = await getScheduledTask(backfillId); + const taskRecord = await getScheduledTask(es, backfillId); expect(taskRecord.type).to.eql('task'); expect(taskRecord.task.taskType).to.eql('ad_hoc_run-backfill'); expect(taskRecord.task.timeoutOverride).to.eql('10s'); @@ -579,6 +550,8 @@ export default function createBackfillTaskRunnerTests({ getService }: FtrProvide // get the execute-backfill events const events: IValidatedEvent[] = await waitForEventLogDocs( + retry, + getService, backfillId, spaceId, new Map([['execute-backfill', { equal: 4 }]]) @@ -652,83 +625,8 @@ export default function createBackfillTaskRunnerTests({ getService }: FtrProvide ); // task should have been deleted after backfill runs have finished - const numHits = await searchScheduledTask(backfillId); + const numHits = await searchScheduledTask(es, backfillId); expect(numHits).to.eql(0); }); - - async function indexTestDocs() { - await asyncForEach(originalDocTimestamps, async (timestamp: string) => { - await createEsDocument(es, new Date(timestamp).valueOf(), 1, ES_TEST_INDEX_NAME); - }); - - await esTestIndexTool.waitForDocs( - DOCUMENT_SOURCE, - DOCUMENT_REFERENCE, - originalDocTimestamps.length - ); - } }); - - async function queryForAlertDocs(): Promise>> { - const searchResult = await es.search({ - index: alertsAsDataIndex, - body: { - sort: [{ [ALERT_ORIGINAL_TIME]: { order: 'asc' } }], - query: { match_all: {} }, - }, - }); - return searchResult.hits.hits as Array>; - } - - async function waitForEventLogDocs( - id: string, - spaceId: string, - actions: Map - ) { - return await retry.try(async () => { - return await getEventLog({ - getService, - spaceId, - type: AD_HOC_RUN_SAVED_OBJECT_TYPE, - id, - provider: 'alerting', - actions, - }); - }); - } - - async function getScheduledTask(id: string): Promise { - const scheduledTask = await es.get({ - id: `task:${id}`, - index: '.kibana_task_manager', - }); - return scheduledTask._source!; - } - - async function searchScheduledTask(id: string) { - const searchResult = await es.search({ - index: '.kibana_task_manager', - body: { - query: { - bool: { - must: [ - { - term: { - 'task.id': `task:${id}`, - }, - }, - { - terms: { - 'task.scope': ['alerting'], - }, - }, - ], - }, - }, - }, - }); - - // @ts-expect-error - return searchResult.hits.total.value; - } } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/task_runner_with_actions.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/task_runner_with_actions.ts new file mode 100644 index 0000000000000..f155f40a61f05 --- /dev/null +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/task_runner_with_actions.ts @@ -0,0 +1,267 @@ +/* + * 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 expect from '@kbn/expect'; +import moment from 'moment'; +import { ESTestIndexTool } from '@kbn/alerting-api-integration-helpers'; +import { asyncForEach } from '../../../../../../functional/services/transform/api'; +import { SuperuserAtSpace1 } from '../../../../scenarios'; +import { getUrlPrefix, ObjectRemover } from '../../../../../common/lib'; +import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { + TEST_ACTIONS_INDEX, + indexTestDocs, + getSecurityRule, + testDocTimestamps, + waitForEventLogDocs, +} from './test_utils'; + +// eslint-disable-next-line import/no-default-export +export default function scheduleBackfillTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const es = getService('es'); + const retry = getService('retry'); + const esTestIndexTool = new ESTestIndexTool(es, retry); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + + describe('ad hoc backfill with rule actions', () => { + const spaceId = SuperuserAtSpace1.space.id; + let backfillIds: string[] = []; + const objectRemover = new ObjectRemover(supertest); + let connectorId: string; + + beforeEach(async () => { + await esTestIndexTool.destroy(); + await esTestIndexTool.setup(); + + // Index documents + await indexTestDocs(es, esTestIndexTool); + + // create a connector + const cresponse = await supertest + .post(`${getUrlPrefix(spaceId)}/api/actions/connector`) + .set('kbn-xsrf', 'foo') + .auth(SuperuserAtSpace1.user.username, SuperuserAtSpace1.user.password) + .send({ + name: 'An index connector', + connector_type_id: '.index', + config: { + index: TEST_ACTIONS_INDEX, + refresh: true, + }, + secrets: {}, + }) + .expect(200); + connectorId = cresponse.body.id; + objectRemover.add(spaceId, connectorId, 'connector', 'actions'); + }); + + afterEach(async () => { + await es.deleteByQuery({ + index: TEST_ACTIONS_INDEX, + query: { match_all: {} }, + conflicts: 'proceed', + }); + await asyncForEach(backfillIds, async (id: string) => { + await supertest + .delete(`${getUrlPrefix(spaceId)}/internal/alerting/rules/backfill/${id}`) + .set('kbn-xsrf', 'foo'); + }); + backfillIds = []; + await objectRemover.removeAll(); + await esTestIndexTool.destroy(); + }); + + it('should run summary actions for backfill jobs when run_actions=true', async () => { + // create a siem query rule with an action + const rresponse = await supertest + .post(`${getUrlPrefix(spaceId)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .auth(SuperuserAtSpace1.user.username, SuperuserAtSpace1.user.password) + .send( + getSecurityRule({ + actions: [ + { + group: 'default', + id: connectorId, + params: { documents: [{ alertUuid: '{{alert.uuid}}' }] }, + frequency: { notify_when: 'onActiveAlert', throttle: null, summary: true }, + }, + ], + }) + ) + .expect(200); + + const ruleId = rresponse.body.id; + objectRemover.add(spaceId, ruleId, 'rule', 'alerting'); + + const start = moment(testDocTimestamps[1]).utc().startOf('day').toISOString(); + const end = moment(testDocTimestamps[11]).utc().startOf('day').toISOString(); + + // schedule backfill for this rule + const response = await supertestWithoutAuth + .post(`${getUrlPrefix(spaceId)}/internal/alerting/rules/backfill/_schedule`) + .set('kbn-xsrf', 'foo') + .auth(SuperuserAtSpace1.user.username, SuperuserAtSpace1.user.password) + .send([{ rule_id: ruleId, start, end, run_actions: true }]) + .expect(200); + + const scheduleResult = response.body; + expect(scheduleResult.length).to.eql(1); + expect(scheduleResult[0].schedule.length).to.eql(4); + + const backfillId = scheduleResult[0].id; + + // wait for backfills to run + await waitForEventLogDocs( + retry, + getService, + backfillId, + spaceId, + new Map([['execute-backfill', { equal: 4 }]]) + ); + + await retry.try(async () => { + // verify that the correct number of actions were executed + const actions = await es.search({ + index: TEST_ACTIONS_INDEX, + body: { query: { match_all: {} } }, + }); + + // 3 backfill executions resulted in alerts so 3 notifications should have + // been generated. + expect(actions.hits.hits.length).to.eql(3); + }); + }); + + it('should run per-alert actions for backfill jobs when run_actions=true', async () => { + // create a siem query rule with an action + const rresponse = await supertest + .post(`${getUrlPrefix(spaceId)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .auth(SuperuserAtSpace1.user.username, SuperuserAtSpace1.user.password) + .send( + getSecurityRule({ + actions: [ + { + group: 'default', + id: connectorId, + params: { documents: [{ alertUuid: '{{alert.uuid}}' }] }, + frequency: { notify_when: 'onActiveAlert', throttle: null, summary: false }, + }, + ], + }) + ) + .expect(200); + + const ruleId = rresponse.body.id; + objectRemover.add(spaceId, ruleId, 'rule', 'alerting'); + + const start = moment(testDocTimestamps[1]).utc().startOf('day').toISOString(); + const end = moment(testDocTimestamps[11]).utc().startOf('day').toISOString(); + + // schedule backfill for this rule + const response = await supertestWithoutAuth + .post(`${getUrlPrefix(spaceId)}/internal/alerting/rules/backfill/_schedule`) + .set('kbn-xsrf', 'foo') + .auth(SuperuserAtSpace1.user.username, SuperuserAtSpace1.user.password) + .send([{ rule_id: ruleId, start, end, run_actions: true }]) + .expect(200); + + const scheduleResult = response.body; + expect(scheduleResult.length).to.eql(1); + expect(scheduleResult[0].schedule.length).to.eql(4); + + const backfillId = scheduleResult[0].id; + + // wait for backfills to run + await waitForEventLogDocs( + retry, + getService, + backfillId, + spaceId, + new Map([['execute-backfill', { equal: 4 }]]) + ); + + await retry.try(async () => { + // verify that the correct number of actions were executed + const actions = await es.search({ + index: TEST_ACTIONS_INDEX, + body: { query: { match_all: {} } }, + }); + + // 3 backfill executions resulted in 9 alerts so 9 notifications should have + // been generated. + expect(actions.hits.hits.length).to.eql(9); + }); + }); + + it('should not run actions for backfill jobs when run_actions=false', async () => { + // create a siem query rule with an action + const rresponse = await supertest + .post(`${getUrlPrefix(spaceId)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .auth(SuperuserAtSpace1.user.username, SuperuserAtSpace1.user.password) + .send( + getSecurityRule({ + actions: [ + { + group: 'default', + id: connectorId, + params: { documents: [{ alertUuid: '{{alert.uuid}}' }] }, + frequency: { notify_when: 'onActiveAlert', throttle: null, summary: true }, + }, + ], + }) + ) + .expect(200); + + const ruleId = rresponse.body.id; + objectRemover.add(spaceId, ruleId, 'rule', 'alerting'); + + const start = moment(testDocTimestamps[1]).utc().startOf('day').toISOString(); + const end = moment(testDocTimestamps[11]).utc().startOf('day').toISOString(); + + // schedule backfill for this rule + const response = await supertestWithoutAuth + .post(`${getUrlPrefix(spaceId)}/internal/alerting/rules/backfill/_schedule`) + .set('kbn-xsrf', 'foo') + .auth(SuperuserAtSpace1.user.username, SuperuserAtSpace1.user.password) + .send([{ rule_id: ruleId, start, end, run_actions: false }]) + .expect(200); + + const scheduleResult = response.body; + expect(scheduleResult.length).to.eql(1); + expect(scheduleResult[0].schedule.length).to.eql(4); + expect(scheduleResult[0].rule.actions).to.eql([]); + + const backfillId = scheduleResult[0].id; + + // wait for backfills to run + await waitForEventLogDocs( + retry, + getService, + backfillId, + spaceId, + new Map([['execute-backfill', { equal: 4 }]]) + ); + + // since we want to check that no actions were executed and they might take a bit to run + // add a small delay + await new Promise((resolve) => setTimeout(resolve, 5000)); + + // verify that the correct number of actions were executed + const actions = await es.search({ + index: TEST_ACTIONS_INDEX, + body: { query: { match_all: {} } }, + }); + + // no actions should be generated + expect(actions.hits.hits.length).to.eql(0); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/test_utils.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/test_utils.ts new file mode 100644 index 0000000000000..ad4fde6b39ec6 --- /dev/null +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/test_utils.ts @@ -0,0 +1,166 @@ +/* + * 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 { asyncForEach } from '@kbn/std'; +import { ESTestIndexTool, ES_TEST_INDEX_NAME } from '@kbn/alerting-api-integration-helpers'; +import type { Client } from '@elastic/elasticsearch'; +import moment from 'moment'; +import { FtrProviderContext, RetryService } from '@kbn/ftr-common-functional-services'; +import { AD_HOC_RUN_SAVED_OBJECT_TYPE } from '@kbn/alerting-plugin/server/saved_objects'; +import { ALERT_ORIGINAL_TIME } from '@kbn/security-solution-plugin/common/field_maps/field_names'; +import { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { TaskManagerDoc, getEventLog } from '../../../../../common/lib'; +import { + DOCUMENT_REFERENCE, + DOCUMENT_SOURCE, + createEsDocument, +} from '../../../../../spaces_only/tests/alerting/create_test_data'; + +export const TEST_ACTIONS_INDEX = 'alerting-backfill-test-data'; + +export const testDocTimestamps = [ + // before first backfill run + moment().utc().subtract(14, 'days').toISOString(), + + // backfill execution set 1 + moment().utc().startOf('day').subtract(13, 'days').add(10, 'minutes').toISOString(), + moment().utc().startOf('day').subtract(13, 'days').add(11, 'minutes').toISOString(), + moment().utc().startOf('day').subtract(13, 'days').add(12, 'minutes').toISOString(), + + // backfill execution set 2 + moment().utc().startOf('day').subtract(12, 'days').add(20, 'minutes').toISOString(), + + // backfill execution set 3 + moment().utc().startOf('day').subtract(11, 'days').add(30, 'minutes').toISOString(), + moment().utc().startOf('day').subtract(11, 'days').add(31, 'minutes').toISOString(), + moment().utc().startOf('day').subtract(11, 'days').add(32, 'minutes').toISOString(), + moment().utc().startOf('day').subtract(11, 'days').add(33, 'minutes').toISOString(), + moment().utc().startOf('day').subtract(11, 'days').add(34, 'minutes').toISOString(), + + // backfill execution set 4 purposely left empty + + // after last backfill + moment().utc().startOf('day').subtract(9, 'days').add(40, 'minutes').toISOString(), + moment().utc().startOf('day').subtract(9, 'days').add(41, 'minutes').toISOString(), +]; + +export async function indexTestDocs(es: Client, esTestIndexTool: ESTestIndexTool) { + await asyncForEach(testDocTimestamps, async (timestamp: string) => { + await createEsDocument(es, new Date(timestamp).valueOf(), 1, ES_TEST_INDEX_NAME); + }); + + await esTestIndexTool.waitForDocs(DOCUMENT_SOURCE, DOCUMENT_REFERENCE, testDocTimestamps.length); +} + +export async function waitForEventLogDocs( + retry: RetryService, + getService: FtrProviderContext['getService'], + id: string, + spaceId: string, + actions: Map +) { + return await retry.try(async () => { + return await getEventLog({ + getService, + spaceId, + type: AD_HOC_RUN_SAVED_OBJECT_TYPE, + id, + provider: 'alerting', + actions, + }); + }); +} + +export async function getScheduledTask(es: Client, id: string): Promise { + const scheduledTask = await es.get({ + id: `task:${id}`, + index: '.kibana_task_manager', + }); + return scheduledTask._source!; +} + +export async function queryForAlertDocs( + es: Client, + index: string +): Promise>> { + const searchResult = await es.search({ + index, + body: { + sort: [{ [ALERT_ORIGINAL_TIME]: { order: 'asc' } }], + query: { match_all: {} }, + }, + }); + return searchResult.hits.hits as Array>; +} + +export async function searchScheduledTask(es: Client, id: string) { + const searchResult = await es.search({ + index: '.kibana_task_manager', + body: { + query: { + bool: { + must: [ + { + term: { + 'task.id': `task:${id}`, + }, + }, + { + terms: { + 'task.scope': ['alerting'], + }, + }, + ], + }, + }, + }, + }); + + // @ts-expect-error + return searchResult.hits.total.value; +} + +export function getSecurityRule(overwrites = {}) { + return { + name: 'test siem query rule with actions', + rule_type_id: 'siem.queryRule', + consumer: 'siem', + enabled: true, + actions: [], + schedule: { interval: '24h' }, + params: { + author: [], + description: 'test', + falsePositives: [], + from: 'now-86460s', + ruleId: '31c54f10-9d3b-45a8-b064-b92e8c6fcbe7', + immutable: false, + license: '', + outputIndex: '', + meta: { from: '1m', kibana_siem_app_url: 'https://localhost:5601/app/security' }, + maxSignals: 20, + riskScore: 21, + riskScoreMapping: [], + severity: 'low', + severityMapping: [], + threat: [], + to: 'now', + references: [], + version: 1, + exceptionsList: [], + relatedIntegrations: [], + requiredFields: [], + setup: '', + type: 'query', + language: 'kuery', + index: [ES_TEST_INDEX_NAME], + query: `source:${DOCUMENT_SOURCE}`, + filters: [], + }, + ...overwrites, + }; +} diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group4/tests/alerting/alerts.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group4/tests/alerting/alerts.ts index c3cc9f410b203..17f424d4e287f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group4/tests/alerting/alerts.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group4/tests/alerting/alerts.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { expect as expectExpect } from 'expect'; import { omit, padStart } from 'lodash'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { IValidatedEvent, nanosToMillis } from '@kbn/event-log-plugin/server'; import { TaskRunning, TaskRunningStage } from '@kbn/task-manager-plugin/server/task_running'; import { ConcreteTaskInstance } from '@kbn/task-manager-plugin/server'; diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute_unsecured_action.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute_unsecured_action.ts index 508dad042d8c5..91000c6df7d17 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute_unsecured_action.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute_unsecured_action.ts @@ -7,7 +7,7 @@ import getPort from 'get-port'; import expect from '@kbn/expect'; -import type { SearchTotalHits } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { SearchTotalHits } from '@elastic/elasticsearch/lib/api/types'; import { getWebhookServer } from '@kbn/actions-simulators-plugin/server/plugin'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { ObjectRemover } from '../../../common/lib'; diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/schedule_unsecured_action.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/schedule_unsecured_action.ts index f740c82bcbd70..7074cc3c0b6e5 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/schedule_unsecured_action.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/schedule_unsecured_action.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import type { SearchTotalHits } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { SearchTotalHits } from '@elastic/elasticsearch/lib/api/types'; import { Spaces } from '../../scenarios'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { getUrlPrefix, ObjectRemover } from '../../../common/lib'; diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/alerts_base.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/alerts_base.ts index d1883b0be924a..806849f87a90b 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/alerts_base.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/alerts_base.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { omit } from 'lodash'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { Response as SupertestResponse } from 'supertest'; import { RecoveredActionGroup } from '@kbn/alerting-plugin/common'; import { TaskRunning, TaskRunningStage } from '@kbn/task-manager-plugin/server/task_running'; diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alert_severity.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alert_severity.ts index 533bd593e3588..dd9c28fc75737 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alert_severity.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alert_severity.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import type { Alert } from '@kbn/alerts-as-data-utils'; -import { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { SearchHit } from '@elastic/elasticsearch/lib/api/types'; import { ALERT_ACTION_GROUP, ALERT_SEVERITY_IMPROVING, diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data/alerts_as_data.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data/alerts_as_data.ts index 8833800f8215f..760ed4d857daf 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data/alerts_as_data.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data/alerts_as_data.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { SearchHit } from '@elastic/elasticsearch/lib/api/types'; import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { setTimeout as setTimeoutAsync } from 'timers/promises'; import type { Alert } from '@kbn/alerts-as-data-utils'; diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data/alerts_as_data_alert_delay.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data/alerts_as_data_alert_delay.ts index 59068ee945ea2..67f3570aa4089 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data/alerts_as_data_alert_delay.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data/alerts_as_data_alert_delay.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { get } from 'lodash'; -import { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { SearchHit } from '@elastic/elasticsearch/lib/api/types'; import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import type { Alert } from '@kbn/alerts-as-data-utils'; import { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data/alerts_as_data_conflicts.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data/alerts_as_data_conflicts.ts index 4866f8581f0bf..ea2f5537a0cd8 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data/alerts_as_data_conflicts.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data/alerts_as_data_conflicts.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { Client } from '@elastic/elasticsearch'; -import { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { SearchHit } from '@elastic/elasticsearch/lib/api/types'; import type { Alert } from '@kbn/alerts-as-data-utils'; import { ESTestIndexTool } from '@kbn/alerting-api-integration-helpers'; import { basename } from 'node:path'; diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data/alerts_as_data_flapping.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data/alerts_as_data_flapping.ts index 9bab20d763fcb..7e095f578fdf7 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data/alerts_as_data_flapping.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data/alerts_as_data_flapping.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { SearchHit } from '@elastic/elasticsearch/lib/api/types'; import type { Alert } from '@kbn/alerts-as-data-utils'; import { RuleNotifyWhen } from '@kbn/alerting-plugin/common'; import { setTimeout as setTimeoutAsync } from 'timers/promises'; diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/migrations.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/migrations.ts index 2cb5a616320eb..5e8db619d34a6 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/migrations.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/migrations.ts @@ -6,7 +6,7 @@ */ import expect from 'expect'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import type { RawRule, RawRuleAction } from '@kbn/alerting-plugin/server/types'; import { FILEBEAT_7X_INDICATOR_PATH } from '@kbn/alerting-plugin/server/saved_objects/migrations'; import type { SavedObjectReference } from '@kbn/core/server'; diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts b/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts index 3ad0ef88ef75a..4d244391cf3d3 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts @@ -194,7 +194,7 @@ export const createCSPRole = async ( await security.role.create(roleName, { kibana: [ { - feature: { siem: ['read'], fleetv2: ['all'], fleet: ['read'] }, + feature: { siemV2: ['read'], fleetv2: ['all'], fleet: ['read'] }, spaces: ['*'], }, ], diff --git a/x-pack/test/api_integration/apis/features/features/features.ts b/x-pack/test/api_integration/apis/features/features/features.ts index 4ca972549f0cb..fe33d3483150b 100644 --- a/x-pack/test/api_integration/apis/features/features/features.ts +++ b/x-pack/test/api_integration/apis/features/features/features.ts @@ -132,11 +132,13 @@ export default function ({ getService }: FtrProviderContext) { 'uptime', 'searchInferenceEndpoints', 'searchPlayground', - 'siem', + 'siemV2', 'slo', 'securitySolutionAssistant', 'securitySolutionAttackDiscovery', 'securitySolutionCasesV2', + 'securitySolutionTimeline', + 'securitySolutionNotes', 'fleet', 'fleetv2', 'entityManager', @@ -188,10 +190,13 @@ export default function ({ getService }: FtrProviderContext) { 'searchSynonyms', 'searchPlayground', 'siem', + 'siemV2', 'slo', 'securitySolutionAssistant', 'securitySolutionAttackDiscovery', 'securitySolutionCasesV2', + 'securitySolutionTimeline', + 'securitySolutionNotes', 'fleet', 'fleetv2', 'entityManager', diff --git a/x-pack/test/api_integration/apis/search/config.ts b/x-pack/test/api_integration/apis/search/config.ts index 5f335f116fefe..3eee82a5988b2 100644 --- a/x-pack/test/api_integration/apis/search/config.ts +++ b/x-pack/test/api_integration/apis/search/config.ts @@ -13,5 +13,12 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { return { ...baseIntegrationTestsConfig.getAll(), testFiles: [require.resolve('.')], + kbnTestServer: { + ...baseIntegrationTestsConfig.get('kbnTestServer'), + serverArgs: [ + ...baseIntegrationTestsConfig.get('kbnTestServer.serverArgs'), + '--data.search.sessions.enabled=true', // enable search sessions + ], + }, }; } diff --git a/x-pack/test/api_integration/apis/security/privileges.ts b/x-pack/test/api_integration/apis/security/privileges.ts index 015dbb27b6455..523ade57c53c6 100644 --- a/x-pack/test/api_integration/apis/security/privileges.ts +++ b/x-pack/test/api_integration/apis/security/privileges.ts @@ -103,6 +103,31 @@ export default function ({ getService }: FtrProviderContext) { 'execute_operations_all', 'scan_operations_all', ], + siemV2: [ + 'all', + 'read', + 'minimal_all', + 'minimal_read', + 'endpoint_list_all', + 'endpoint_list_read', + 'trusted_applications_all', + 'trusted_applications_read', + 'host_isolation_exceptions_all', + 'host_isolation_exceptions_read', + 'blocklist_all', + 'blocklist_read', + 'event_filters_all', + 'event_filters_read', + 'policy_management_all', + 'policy_management_read', + 'actions_log_management_all', + 'actions_log_management_read', + 'host_isolation_all', + 'process_operations_all', + 'file_operations_all', + 'execute_operations_all', + 'scan_operations_all', + ], uptime: [ 'all', 'read', @@ -138,6 +163,8 @@ export default function ({ getService }: FtrProviderContext) { 'create_comment', 'case_reopen', ], + securitySolutionTimeline: ['all', 'read', 'minimal_all', 'minimal_read'], + securitySolutionNotes: ['all', 'read', 'minimal_all', 'minimal_read'], infrastructure: ['all', 'read', 'minimal_all', 'minimal_read'], logs: ['all', 'read', 'minimal_all', 'minimal_read'], dataQuality: ['all', 'read', 'minimal_all', 'minimal_read'], diff --git a/x-pack/test/api_integration/apis/security/privileges_basic.ts b/x-pack/test/api_integration/apis/security/privileges_basic.ts index 6b4f4b505e3ba..0af7857f616c0 100644 --- a/x-pack/test/api_integration/apis/security/privileges_basic.ts +++ b/x-pack/test/api_integration/apis/security/privileges_basic.ts @@ -48,10 +48,13 @@ export default function ({ getService }: FtrProviderContext) { enterpriseSearchAnalytics: ['all', 'read', 'minimal_all', 'minimal_read'], ml: ['all', 'read', 'minimal_all', 'minimal_read'], siem: ['all', 'read', 'minimal_all', 'minimal_read'], + siemV2: ['all', 'read', 'minimal_all', 'minimal_read'], securitySolutionAssistant: ['all', 'read', 'minimal_all', 'minimal_read'], securitySolutionAttackDiscovery: ['all', 'read', 'minimal_all', 'minimal_read'], securitySolutionCases: ['all', 'read', 'minimal_all', 'minimal_read'], securitySolutionCasesV2: ['all', 'read', 'minimal_all', 'minimal_read'], + securitySolutionNotes: ['all', 'read', 'minimal_all', 'minimal_read'], + securitySolutionTimeline: ['all', 'read', 'minimal_all', 'minimal_read'], searchPlayground: ['all', 'read', 'minimal_all', 'minimal_read'], searchInferenceEndpoints: ['all', 'read', 'minimal_all', 'minimal_read'], fleetv2: ['all', 'read', 'minimal_all', 'minimal_read'], @@ -192,6 +195,31 @@ export default function ({ getService }: FtrProviderContext) { 'execute_operations_all', 'scan_operations_all', ], + siemV2: [ + 'actions_log_management_all', + 'actions_log_management_read', + 'all', + 'blocklist_all', + 'blocklist_read', + 'endpoint_list_all', + 'endpoint_list_read', + 'event_filters_all', + 'event_filters_read', + 'host_isolation_all', + 'host_isolation_exceptions_all', + 'host_isolation_exceptions_read', + 'minimal_all', + 'minimal_read', + 'policy_management_all', + 'policy_management_read', + 'process_operations_all', + 'read', + 'trusted_applications_all', + 'trusted_applications_read', + 'file_operations_all', + 'execute_operations_all', + 'scan_operations_all', + ], uptime: [ 'all', 'can_manage_private_locations', @@ -227,6 +255,8 @@ export default function ({ getService }: FtrProviderContext) { 'create_comment', 'case_reopen', ], + securitySolutionTimeline: ['all', 'read', 'minimal_all', 'minimal_read'], + securitySolutionNotes: ['all', 'read', 'minimal_all', 'minimal_read'], infrastructure: ['all', 'read', 'minimal_all', 'minimal_read'], logs: ['all', 'read', 'minimal_all', 'minimal_read'], dataQuality: ['all', 'read', 'minimal_all', 'minimal_read'], diff --git a/x-pack/test/api_integration/apis/streams/config.ts b/x-pack/test/api_integration/apis/streams/config.ts deleted file mode 100644 index 2fbcac9ff3b8d..0000000000000 --- a/x-pack/test/api_integration/apis/streams/config.ts +++ /dev/null @@ -1,30 +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 { FtrConfigProviderContext, getKibanaCliLoggers } from '@kbn/test'; - -export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); - return { - ...baseIntegrationTestsConfig.getAll(), - kbnTestServer: { - ...baseIntegrationTestsConfig.get('kbnTestServer'), - serverArgs: [ - ...baseIntegrationTestsConfig.get('kbnTestServer.serverArgs'), - `--logging.loggers=${JSON.stringify([ - ...getKibanaCliLoggers(baseIntegrationTestsConfig.get('kbnTestServer.serverArgs')), - { - name: 'plugins.streams', - level: 'debug', - appenders: ['default'], - }, - ])}`, - ], - }, - testFiles: [require.resolve('.')], - }; -} diff --git a/x-pack/test/api_integration/apis/streams/schema.ts b/x-pack/test/api_integration/apis/streams/schema.ts deleted file mode 100644 index b65b15f070097..0000000000000 --- a/x-pack/test/api_integration/apis/streams/schema.ts +++ /dev/null @@ -1,95 +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 expect from '@kbn/expect'; -import { - disableStreams, - enableStreams, - forkStream, - getUnmappedFieldsForStream, - indexDocument, - simulateFieldsForStream, -} from './helpers/requests'; -import { FtrProviderContext } from '../../ftr_provider_context'; -import { createStreamsRepositorySupertestClient } from './helpers/repository_client'; - -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const esClient = getService('es'); - - const apiClient = createStreamsRepositorySupertestClient(supertest); - - describe('Streams Schema', () => { - before(async () => { - await enableStreams(apiClient); - - const doc = { - '@timestamp': '2024-01-01T00:00:10.000Z', - message: '2023-01-01T00:00:10.000Z error test', - ['some.field']: 'some value', - ['another.field']: 'another value', - lastField: 'last value', - ['log.level']: 'warning', - }; - - await indexDocument(esClient, 'logs', doc); - }); - - after(async () => { - await disableStreams(apiClient); - }); - - describe('Unmapped fields API', () => { - it('Returns unmapped fields', async () => { - const response = await getUnmappedFieldsForStream(supertest, 'logs'); - expect(response.unmappedFields).to.eql(['another.field', 'lastField', 'some.field']); - }); - }); - - describe('Fields simulation API', () => { - it('Returns failure status when simulation would fail', async () => { - const response = await simulateFieldsForStream(supertest, 'logs', { - field_definitions: [{ name: 'message', type: 'boolean' }], - }); - - expect(response.status).to.be('failure'); - expect(response.simulationError).to.be.a('string'); - expect(response.documentsWithRuntimeFieldsApplied).to.be(null); - }); - it('Returns success status when simulation would succeed', async () => { - const response = await simulateFieldsForStream(supertest, 'logs', { - field_definitions: [{ name: 'message', type: 'keyword' }], - }); - - expect(response.status).to.be('success'); - expect(response.simulationError).to.be(null); - expect(response.documentsWithRuntimeFieldsApplied).length(1); - }); - it('Returns unknown status when documents are missing and status cannot be determined', async () => { - const forkBody = { - stream: { - name: 'logs.nginx', - }, - condition: { - field: 'log.logger', - operator: 'eq' as const, - value: 'nginx', - }, - }; - - await forkStream(apiClient, 'logs', forkBody); - const response = await simulateFieldsForStream(supertest, 'logs.nginx', { - field_definitions: [{ name: 'message', type: 'keyword' }], - }); - - expect(response.status).to.be('unknown'); - expect(response.simulationError).to.be(null); - expect(response.documentsWithRuntimeFieldsApplied).to.be(null); - }); - }); - }); -} diff --git a/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts b/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts index f03cb6fb80e37..d7a96333f49e8 100644 --- a/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts +++ b/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts @@ -48,10 +48,8 @@ export default function ({ getService }: FtrProviderContext) { try { await es.indices.create({ index: indexName, - body: { - settings: { - index: indexSettings, - }, + settings: { + index: indexSettings, }, }); } catch (err) { diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/complete/complete.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/complete/complete.spec.ts index c7497e81d9d2b..1cca90f96ab83 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/complete/complete.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/complete/complete.spec.ts @@ -98,7 +98,19 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon ]); await titleSimulator.status(200); - await titleSimulator.next('My generated title'); + await titleSimulator.next({ + content: '', + tool_calls: [ + { + id: 'id', + index: 0, + function: { + name: 'title_conversation', + arguments: JSON.stringify({ title: 'My generated title' }), + }, + }, + ], + }); await titleSimulator.tokenCount({ completion: 5, prompt: 10, total: 15 }); await titleSimulator.complete(); diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/complete/functions/summarize.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/complete/functions/summarize.spec.ts index 2f372975ee542..804d325cbe3bb 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/complete/functions/summarize.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/complete/functions/summarize.spec.ts @@ -14,17 +14,19 @@ import { import type { DeploymentAgnosticFtrProviderContext } from '../../../../../ftr_provider_context'; import { invokeChatCompleteWithFunctionRequest } from './helpers'; import { - TINY_ELSER, clearKnowledgeBase, - createKnowledgeBaseModel, + importTinyElserModel, deleteInferenceEndpoint, deleteKnowledgeBaseModel, + setupKnowledgeBase, + waitForKnowledgeBaseReady, } from '../../knowledge_base/helpers'; export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { const log = getService('log'); const ml = getService('ml'); const es = getService('es'); + const retry = getService('retry'); const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantApi'); describe('when calling summarize function', function () { @@ -34,16 +36,9 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon let connectorId: string; before(async () => { - await createKnowledgeBaseModel(ml); - const { status } = await observabilityAIAssistantAPIClient.admin({ - endpoint: 'POST /internal/observability_ai_assistant/kb/setup', - params: { - query: { - model_id: TINY_ELSER.id, - }, - }, - }); - expect(status).to.be(200); + await importTinyElserModel(ml); + await setupKnowledgeBase(observabilityAIAssistantAPIClient); + await waitForKnowledgeBaseReady({ observabilityAIAssistantAPIClient, log, retry }); proxy = await createLlmProxy(log); connectorId = await observabilityAIAssistantAPIClient.createProxyActionConnector({ diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/helpers.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/helpers.ts index 833cb0fd010cd..0d36c884f9015 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/helpers.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/helpers.ts @@ -5,8 +5,12 @@ * 2.0. */ +import expect from '@kbn/expect'; import { Client } from '@elastic/elasticsearch'; import { AI_ASSISTANT_KB_INFERENCE_ID } from '@kbn/observability-ai-assistant-plugin/server/service/inference_endpoint'; +import { ToolingLog } from '@kbn/tooling-log'; +import { RetryService } from '@kbn/ftr-common-functional-services'; +import type { ObservabilityAIAssistantApiClient } from '../../../../services/observability_ai_assistant_api'; import { MachineLearningProvider } from '../../../../../services/ml'; import { SUPPORTED_TRAINED_MODELS } from '../../../../../../functional/services/ml/api'; @@ -15,7 +19,7 @@ export const TINY_ELSER = { id: SUPPORTED_TRAINED_MODELS.TINY_ELSER.name, }; -export async function createKnowledgeBaseModel(ml: ReturnType) { +export async function importTinyElserModel(ml: ReturnType) { const config = { ...ml.api.getTrainedModelConfig(TINY_ELSER.name), input: { @@ -27,6 +31,40 @@ export async function createKnowledgeBaseModel(ml: ReturnType { + log.debug(`Waiting for knowledge base to be ready...`); + const res = await observabilityAIAssistantAPIClient.editor({ + endpoint: 'GET /internal/observability_ai_assistant/kb/status', + }); + expect(res.status).to.be(200); + expect(res.body.ready).to.be(true); + }); +} + export async function deleteKnowledgeBaseModel(ml: ReturnType) { await ml.api.stopTrainedModelDeploymentES(TINY_ELSER.id, true); await ml.api.deleteTrainedModelES(TINY_ELSER.id); diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base.spec.ts index 1e3937cd7c1be..8e5e02837be1b 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base.spec.ts @@ -9,34 +9,26 @@ import expect from '@kbn/expect'; import { type KnowledgeBaseEntry } from '@kbn/observability-ai-assistant-plugin/common'; import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; import { - TINY_ELSER, clearKnowledgeBase, - createKnowledgeBaseModel, + importTinyElserModel, deleteInferenceEndpoint, deleteKnowledgeBaseModel, + setupKnowledgeBase, + waitForKnowledgeBaseReady, } from './helpers'; export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { const ml = getService('ml'); const es = getService('es'); + const log = getService('log'); + const retry = getService('retry'); const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantApi'); describe('Knowledge base', function () { - // Fails on MKI: https://github.com/elastic/kibana/issues/205581 - this.tags(['failsOnMKI']); before(async () => { - await createKnowledgeBaseModel(ml); - - const { status } = await observabilityAIAssistantAPIClient.admin({ - endpoint: 'POST /internal/observability_ai_assistant/kb/setup', - params: { - query: { - model_id: TINY_ELSER.id, - }, - }, - }); - - expect(status).to.be(200); + await importTinyElserModel(ml); + await setupKnowledgeBase(observabilityAIAssistantAPIClient); + await waitForKnowledgeBaseReady({ observabilityAIAssistantAPIClient, log, retry }); }); after(async () => { diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_migration.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_migration.spec.ts index 81fd896124692..ae13a3525bae8 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_migration.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_migration.spec.ts @@ -13,10 +13,11 @@ import { KnowledgeBaseEntry } from '@kbn/observability-ai-assistant-plugin/commo import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; import { deleteKnowledgeBaseModel, - createKnowledgeBaseModel, + importTinyElserModel, clearKnowledgeBase, deleteInferenceEndpoint, - TINY_ELSER, + setupKnowledgeBase, + waitForKnowledgeBaseReady, } from './helpers'; interface InferenceChunk { @@ -46,6 +47,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon const es = getService('es'); const ml = getService('ml'); const retry = getService('retry'); + const log = getService('log'); const archive = 'x-pack/test/functional/es_archives/observability/ai_assistant/knowledge_base_8_15'; @@ -67,23 +69,16 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon // Failing: See https://github.com/elastic/kibana/issues/206474 describe.skip('When there are knowledge base entries (from 8.15 or earlier) that does not contain semantic_text embeddings', function () { - // security_exception: action [indices:admin/settings/update] is unauthorized for user [testing-internal] with effective roles [superuser] on restricted indices [.kibana_security_solution_1,.kibana_task_manager_1,.kibana_alerting_cases_1,.kibana_usage_counters_1,.kibana_1,.kibana_ingest_1,.kibana_analytics_1], this action is granted by the index privileges [manage,all] - this.tags(['failsOnMKI']); + // Intentionally skipped on MKI because es_archiver.load is not allowed there, and because the migration scenario being tested is not relevant to MKI. + // https://github.com/elastic/obs-ai-assistant-team/issues/195 + this.tags(['skipMKI']); before(async () => { await clearKnowledgeBase(es); await esArchiver.load(archive); - await createKnowledgeBaseModel(ml); - const { status } = await observabilityAIAssistantAPIClient.admin({ - endpoint: 'POST /internal/observability_ai_assistant/kb/setup', - params: { - query: { - model_id: TINY_ELSER.id, - }, - }, - }); - - expect(status).to.be(200); + await importTinyElserModel(ml); + await setupKnowledgeBase(observabilityAIAssistantAPIClient); + await waitForKnowledgeBaseReady({ observabilityAIAssistantAPIClient, log, retry }); }); after(async () => { diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_setup.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_setup.spec.ts index 07782b7be5082..84409e960966e 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_setup.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_setup.spec.ts @@ -9,9 +9,10 @@ import expect from '@kbn/expect'; import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; import { deleteKnowledgeBaseModel, - createKnowledgeBaseModel, + importTinyElserModel, TINY_ELSER, deleteInferenceEndpoint, + setupKnowledgeBase, } from './helpers'; export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { @@ -26,17 +27,8 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon }); it('returns model info when successful', async () => { - await createKnowledgeBaseModel(ml); - const res = await observabilityAIAssistantAPIClient.admin({ - endpoint: 'POST /internal/observability_ai_assistant/kb/setup', - params: { - query: { - model_id: TINY_ELSER.id, - }, - }, - }); - - expect(res.status).to.be(200); + await importTinyElserModel(ml); + const res = await setupKnowledgeBase(observabilityAIAssistantAPIClient); expect(res.body.service_settings.model_id).to.be('pt_tiny_elser'); expect(res.body.inference_id).to.be('obs_ai_assistant_kb_inference'); @@ -46,15 +38,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon }); it('returns error message if model is not deployed', async () => { - const res = await observabilityAIAssistantAPIClient.admin({ - endpoint: 'POST /internal/observability_ai_assistant/kb/setup', - params: { - query: { - model_id: TINY_ELSER.id, - }, - }, - }); - + const res = await setupKnowledgeBase(observabilityAIAssistantAPIClient); expect(res.status).to.be(500); // @ts-expect-error diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_status.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_status.spec.ts index 0bfc51e38092c..127015bdf4925 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_status.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_status.spec.ts @@ -10,32 +10,25 @@ import { AI_ASSISTANT_KB_INFERENCE_ID } from '@kbn/observability-ai-assistant-pl import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; import { deleteKnowledgeBaseModel, - createKnowledgeBaseModel, + importTinyElserModel, TINY_ELSER, deleteInferenceEndpoint, + setupKnowledgeBase, + waitForKnowledgeBaseReady, } from './helpers'; export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { const ml = getService('ml'); const es = getService('es'); + const log = getService('log'); + const retry = getService('retry'); const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantApi'); describe('/internal/observability_ai_assistant/kb/status', function () { - // Fails on MKI: https://github.com/elastic/kibana/issues/205677 - this.tags(['failsOnMKI']); - beforeEach(async () => { - await createKnowledgeBaseModel(ml); - const { status } = await observabilityAIAssistantAPIClient.admin({ - endpoint: 'POST /internal/observability_ai_assistant/kb/setup', - params: { - query: { - model_id: TINY_ELSER.id, - }, - }, - }); - - expect(status).to.be(200); + await importTinyElserModel(ml); + await setupKnowledgeBase(observabilityAIAssistantAPIClient); + await waitForKnowledgeBaseReady({ observabilityAIAssistantAPIClient, log, retry }); }); afterEach(async () => { diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_user_instructions.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_user_instructions.spec.ts index d5fdbd722620a..a1068a1a66ccf 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_user_instructions.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_user_instructions.spec.ts @@ -10,14 +10,16 @@ import { sortBy } from 'lodash'; import { Message, MessageRole } from '@kbn/observability-ai-assistant-plugin/common'; import { CONTEXT_FUNCTION_NAME } from '@kbn/observability-ai-assistant-plugin/server/functions/context'; import { Instruction } from '@kbn/observability-ai-assistant-plugin/common/types'; +import pRetry from 'p-retry'; import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; import { - TINY_ELSER, clearConversations, clearKnowledgeBase, - createKnowledgeBaseModel, + importTinyElserModel, deleteInferenceEndpoint, deleteKnowledgeBaseModel, + setupKnowledgeBase, + waitForKnowledgeBaseReady, } from './helpers'; import { getConversationCreatedEvent } from '../helpers'; import { @@ -25,6 +27,8 @@ import { createLlmProxy, } from '../../../../../../observability_ai_assistant_api_integration/common/create_llm_proxy'; +const sortById = (data: Array) => sortBy(data, 'id'); + export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantApi'); const es = getService('es'); @@ -33,19 +37,10 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon const retry = getService('retry'); describe('Knowledge base user instructions', function () { - // Fails on MKI: https://github.com/elastic/kibana/issues/205581 - this.tags(['failsOnMKI']); before(async () => { - await createKnowledgeBaseModel(ml); - const { status } = await observabilityAIAssistantAPIClient.admin({ - endpoint: 'POST /internal/observability_ai_assistant/kb/setup', - params: { - query: { - model_id: TINY_ELSER.id, - }, - }, - }); - expect(status).to.be(200); + await importTinyElserModel(ml); + await setupKnowledgeBase(observabilityAIAssistantAPIClient); + await waitForKnowledgeBaseReady({ observabilityAIAssistantAPIClient, log, retry }); }); after(async () => { @@ -69,18 +64,17 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon isPublic: false, }, { - username: 'secondary_editor' as const, + username: 'admin' as const, isPublic: true, }, { - username: 'secondary_editor' as const, + username: 'admin' as const, isPublic: false, }, ].map(async ({ username, isPublic }) => { const visibility = isPublic ? 'Public' : 'Private'; - const user = username === 'editor' ? 'editor' : 'admin'; - const { status } = await observabilityAIAssistantAPIClient[user]({ + const { status } = await observabilityAIAssistantAPIClient[username]({ endpoint: 'PUT /internal/observability_ai_assistant/kb/user_instructions', params: { body: { @@ -95,6 +89,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon await Promise.all(promises); }); + it('"editor" can retrieve their own private instructions and the public instruction', async () => { await retry.try(async () => { const res = await observabilityAIAssistantAPIClient.editor({ @@ -104,8 +99,6 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon const instructions = res.body.userInstructions; expect(instructions).to.have.length(3); - const sortById = (data: Array) => sortBy(data, 'id'); - expect(sortById(instructions)).to.eql( sortById([ { @@ -119,9 +112,9 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon text: 'Public user instruction from "editor"', }, { - id: 'public-doc-from-secondary_editor', + id: 'public-doc-from-admin', public: true, - text: 'Public user instruction from "secondary_editor"', + text: 'Public user instruction from "admin"', }, ]) ); @@ -137,8 +130,6 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon const instructions = res.body.userInstructions; expect(instructions).to.have.length(3); - const sortById = (data: Array) => sortBy(data, 'id'); - expect(sortById(instructions)).to.eql( sortById([ { @@ -147,20 +138,79 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon text: 'Public user instruction from "editor"', }, { - id: 'public-doc-from-secondary_editor', + id: 'public-doc-from-admin', public: true, - text: 'Public user instruction from "secondary_editor"', + text: 'Public user instruction from "admin"', }, { - id: 'private-doc-from-secondary_editor', + id: 'private-doc-from-admin', public: false, - text: 'Private user instruction from "secondary_editor"', + text: 'Private user instruction from "admin"', }, ]) ); }); }); }); + + describe('when a public instruction already exists', () => { + const adminInstruction = { + id: `public-doc-from-admin-not-to-be-overwritten`, + text: `public user instruction from "admin" not to be overwritten by other users`, + public: true, + }; + + const editorInstruction = { + id: `public-doc-from-editor-must-not-overwrite-admin-instruction`, + text: `public user instruction from "admin" must not overwrite admin instruction`, + public: true, + }; + + before(async () => { + await clearKnowledgeBase(es); + + const { status: statusAdmin } = await observabilityAIAssistantAPIClient.admin({ + endpoint: 'PUT /internal/observability_ai_assistant/kb/user_instructions', + params: { body: adminInstruction }, + }); + + expect(statusAdmin).to.be(200); + + // wait for the public instruction to be indexed before proceeding + await pRetry(async () => { + const res = await observabilityAIAssistantAPIClient.editor({ + endpoint: 'GET /internal/observability_ai_assistant/kb/user_instructions', + }); + + const hasPublicAdminInstruction = res.body.userInstructions.some( + (instruction) => instruction.id === 'public-doc-from-admin-not-to-be-overwritten' + ); + + if (!hasPublicAdminInstruction) { + throw new Error('Public instruction not found'); + } + }); + + const { status: statusEditor } = await observabilityAIAssistantAPIClient.editor({ + endpoint: 'PUT /internal/observability_ai_assistant/kb/user_instructions', + params: { + body: editorInstruction, + }, + }); + + expect(statusEditor).to.be(200); + }); + + it("another user's public instruction will not overwrite it", async () => { + const res = await observabilityAIAssistantAPIClient.editor({ + endpoint: 'GET /internal/observability_ai_assistant/kb/user_instructions', + }); + + const instructions = res.body.userInstructions; + expect(sortById(instructions)).to.eql(sortById([adminInstruction, editorInstruction])); + }); + }); + describe('when updating an existing user instructions', () => { before(async () => { await clearKnowledgeBase(es); @@ -207,15 +257,16 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon }); describe('when a user instruction exist and a conversation is created', () => { + // Fails on MKI because the LLM Proxy does not yet work there: https://github.com/elastic/obs-ai-assistant-team/issues/199 + this.tags(['failsOnMKI']); + let proxy: LlmProxy; let connectorId: string; const userInstructionText = 'Be polite and use language that is easy to understand. Never disagree with the user.'; - async function getConversationForUser(username: string) { - const user = username === 'editor' ? 'editor' : 'admin'; - + async function getConversationForUser(username: 'editor' | 'admin') { // the user instruction is always created by "editor" user const { status } = await observabilityAIAssistantAPIClient.editor({ endpoint: 'PUT /internal/observability_ai_assistant/kb/user_instructions', @@ -251,7 +302,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon }, ]; - const createResponse = await observabilityAIAssistantAPIClient[user]({ + const createResponse = await observabilityAIAssistantAPIClient[username]({ endpoint: 'POST /internal/observability_ai_assistant/chat/complete', params: { body: { @@ -269,7 +320,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon const conversationCreatedEvent = getConversationCreatedEvent(createResponse.body); const conversationId = conversationCreatedEvent.conversation.id; - const res = await observabilityAIAssistantAPIClient[user]({ + const res = await observabilityAIAssistantAPIClient[username]({ endpoint: 'GET /internal/observability_ai_assistant/conversation/{conversationId}', params: { path: { @@ -323,7 +374,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon }); it('does not add the instruction conversation for other users', async () => { - const conversation = await getConversationForUser('secondary_editor'); + const conversation = await getConversationForUser('admin'); const systemMessage = conversation.messages.find( (message) => message.message.role === MessageRole.System )!; diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/create_slo.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/create_slo.ts index 28cef8c2c566c..b263f86472fef 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/create_slo.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/create_slo.ts @@ -29,6 +29,8 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { let transformHelper: TransformHelper; describe('Create SLOs', function () { + // see details: https://github.com/elastic/kibana/issues/207354 + this.tags(['failsOnMKI']); before(async () => { adminRoleAuthc = await samlAuth.createM2mApiKeyWithRoleScope('admin'); transformHelper = createTransformHelper(getService); @@ -62,7 +64,9 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { expect(definitions.results[0]).eql({ budgetingMethod: 'occurrences', updatedAt: definitions.results[0].updatedAt, + updatedBy: 'elastic_admin', createdAt: definitions.results[0].createdAt, + createdBy: 'elastic_admin', description: 'Fixture for api integration tests', enabled: true, groupBy: 'tags', @@ -98,7 +102,7 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { const rollUpTransformResponse = await transformHelper.assertExist(getSLOTransformId(id, 1)); expect(rollUpTransformResponse.transforms[0].source.index).eql(['kbn-data-forge*']); expect(rollUpTransformResponse.transforms[0].dest).eql({ - index: '.slo-observability.sli-v3.3', + index: '.slo-observability.sli-v3.4', pipeline: `.slo-observability.sli.pipeline-${id}-1`, }); expect(rollUpTransformResponse.transforms[0].pivot.group_by).eql({ @@ -110,10 +114,10 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { getSLOSummaryTransformId(id, 1) ); expect(summaryTransformResponse.transforms[0].source.index).eql([ - '.slo-observability.sli-v3.3*', + '.slo-observability.sli-v3.4*', ]); expect(summaryTransformResponse.transforms[0].dest).eql({ - index: '.slo-observability.summary-v3.3', + index: '.slo-observability.summary-v3.4', pipeline: `.slo-observability.summary.pipeline-${id}-1`, }); }); diff --git a/x-pack/test/api_integration/apis/streams/assets/dashboard.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/assets/dashboard.ts similarity index 94% rename from x-pack/test/api_integration/apis/streams/assets/dashboard.ts rename to x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/assets/dashboard.ts index 6c5fc9f89be3c..da114d49b01ea 100644 --- a/x-pack/test/api_integration/apis/streams/assets/dashboard.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/assets/dashboard.ts @@ -6,16 +6,19 @@ */ import expect from '@kbn/expect'; import { disableStreams, enableStreams, indexDocument } from '../helpers/requests'; -import { createStreamsRepositorySupertestClient } from '../helpers/repository_client'; -import { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); +import { + StreamsSupertestRepositoryClient, + createStreamsRepositoryAdminClient, +} from '../helpers/repository_client'; +import { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; + +export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { + const roleScopedSupertest = getService('roleScopedSupertest'); const esClient = getService('es'); - const kibanaServer = getService('kibanaServer'); + let apiClient: StreamsSupertestRepositoryClient; - const apiClient = createStreamsRepositorySupertestClient(supertest); + const kibanaServer = getService('kibanaServer'); const SPACE_ID = 'default'; const ARCHIVES = [ @@ -105,8 +108,11 @@ export default function ({ getService }: FtrProviderContext) { } } - describe('Asset links', () => { + describe('Asset links', function () { + // see details: https://github.com/elastic/kibana/issues/207310 + this.tags(['failsOnMKI']); before(async () => { + apiClient = await createStreamsRepositoryAdminClient(roleScopedSupertest); await enableStreams(apiClient); await indexDocument(esClient, 'logs', { diff --git a/x-pack/test/api_integration/apis/streams/classic.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/classic.ts similarity index 88% rename from x-pack/test/api_integration/apis/streams/classic.ts rename to x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/classic.ts index 33b875e23d1cf..92331eff6d844 100644 --- a/x-pack/test/api_integration/apis/streams/classic.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/classic.ts @@ -6,20 +6,26 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; -import { createStreamsRepositorySupertestClient } from './helpers/repository_client'; +import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context'; +import { + StreamsSupertestRepositoryClient, + createStreamsRepositoryAdminClient, +} from './helpers/repository_client'; import { disableStreams, enableStreams, fetchDocument, indexDocument } from './helpers/requests'; -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); +export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { + const roleScopedSupertest = getService('roleScopedSupertest'); const esClient = getService('es'); + const config = getService('config'); + const isServerless = !!config.get('serverless'); const TEST_STREAM_NAME = 'logs-test-default'; - const apiClient = createStreamsRepositorySupertestClient(supertest); + let apiClient: StreamsSupertestRepositoryClient; describe('Classic streams', () => { before(async () => { + apiClient = await createStreamsRepositoryAdminClient(roleScopedSupertest); await enableStreams(apiClient); }); @@ -94,10 +100,12 @@ export default function ({ getService }: FtrProviderContext) { name: TEST_STREAM_NAME, dashboards: [], inherited_fields: {}, - lifecycle: { - policy: 'logs', - type: 'ilm', - }, + lifecycle: isServerless + ? { type: 'dlm' } + : { + policy: 'logs', + type: 'ilm', + }, stream: { ingest: { processing: [ diff --git a/x-pack/test/api_integration/apis/streams/enrichment.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/enrichment.ts similarity index 91% rename from x-pack/test/api_integration/apis/streams/enrichment.ts rename to x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/enrichment.ts index 6b3a7a991bafd..72e025c51841f 100644 --- a/x-pack/test/api_integration/apis/streams/enrichment.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/enrichment.ts @@ -16,17 +16,20 @@ import { indexDocument, putStream, } from './helpers/requests'; -import { FtrProviderContext } from '../../ftr_provider_context'; -import { createStreamsRepositorySupertestClient } from './helpers/repository_client'; +import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context'; +import { + StreamsSupertestRepositoryClient, + createStreamsRepositoryAdminClient, +} from './helpers/repository_client'; -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); +export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { + const roleScopedSupertest = getService('roleScopedSupertest'); const esClient = getService('es'); - - const apiClient = createStreamsRepositorySupertestClient(supertest); + let apiClient: StreamsSupertestRepositoryClient; describe('Enrichment', () => { before(async () => { + apiClient = await createStreamsRepositoryAdminClient(roleScopedSupertest); await enableStreams(apiClient); const body = { stream: { diff --git a/x-pack/test/api_integration/apis/streams/flush_config.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/flush_config.ts similarity index 92% rename from x-pack/test/api_integration/apis/streams/flush_config.ts rename to x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/flush_config.ts index 9345d4be31303..02c8652cb3bf9 100644 --- a/x-pack/test/api_integration/apis/streams/flush_config.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/flush_config.ts @@ -9,8 +9,11 @@ import expect from '@kbn/expect'; import { ClientRequestParamsOf } from '@kbn/server-route-repository-utils'; import type { StreamsRouteRepository } from '@kbn/streams-plugin/server'; import { ReadStreamDefinition, WiredReadStreamDefinition } from '@kbn/streams-schema'; -import { FtrProviderContext } from '../../ftr_provider_context'; -import { createStreamsRepositorySupertestClient } from './helpers/repository_client'; +import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context'; +import { + StreamsSupertestRepositoryClient, + createStreamsRepositoryAdminClient, +} from './helpers/repository_client'; import { disableStreams, enableStreams, indexDocument } from './helpers/requests'; type StreamPutItem = ClientRequestParamsOf< @@ -120,15 +123,16 @@ const streams: StreamPutItem[] = [ }, ]; -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); +export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { + const roleScopedSupertest = getService('roleScopedSupertest'); const esClient = getService('es'); - const apiClient = createStreamsRepositorySupertestClient(supertest); + let apiClient: StreamsSupertestRepositoryClient; // An anticipated use case is that a user will want to flush a tree of streams from a config file describe('Flush from config file', () => { before(async () => { + apiClient = await createStreamsRepositoryAdminClient(roleScopedSupertest); await enableStreams(apiClient); await createStreams(); await indexDocuments(); diff --git a/x-pack/test/api_integration/apis/streams/full_flow.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/full_flow.ts similarity index 94% rename from x-pack/test/api_integration/apis/streams/full_flow.ts rename to x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/full_flow.ts index e940c273b9d3c..a259a7984f896 100644 --- a/x-pack/test/api_integration/apis/streams/full_flow.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/full_flow.ts @@ -6,8 +6,11 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; -import { createStreamsRepositorySupertestClient } from './helpers/repository_client'; +import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context'; +import { + StreamsSupertestRepositoryClient, + createStreamsRepositoryAdminClient, +} from './helpers/repository_client'; import { disableStreams, enableStreams, @@ -16,12 +19,11 @@ import { indexDocument, } from './helpers/requests'; -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); +export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { + const roleScopedSupertest = getService('roleScopedSupertest'); + let apiClient: StreamsSupertestRepositoryClient; const esClient = getService('es'); - const apiClient = createStreamsRepositorySupertestClient(supertest); - interface Resources { indices: string[]; componentTemplates: string[]; @@ -57,6 +59,10 @@ export default function ({ getService }: FtrProviderContext) { return response.body.enabled; } + before(async () => { + apiClient = await createStreamsRepositoryAdminClient(roleScopedSupertest); + }); + describe('initially', () => { let resources: Resources; diff --git a/x-pack/test/api_integration/apis/streams/helpers/repository_client.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/helpers/repository_client.ts similarity index 52% rename from x-pack/test/api_integration/apis/streams/helpers/repository_client.ts rename to x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/helpers/repository_client.ts index 4820fb724b6d1..398143709415c 100644 --- a/x-pack/test/api_integration/apis/streams/helpers/repository_client.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/helpers/repository_client.ts @@ -5,16 +5,16 @@ * 2.0. */ import type { StreamsRouteRepository } from '@kbn/streams-plugin/server'; -import supertest from 'supertest'; +import { RoleScopedSupertestProvider } from '../../../../services/role_scoped_supertest'; import { RepositorySupertestClient, - getApiClientFromSupertest, -} from '../../../../common/utils/server_route_repository/create_supertest_service_from_repository'; + getAdminApiClient, +} from '../../../../../../common/utils/server_route_repository/create_admin_service_from_repository'; export type StreamsSupertestRepositoryClient = RepositorySupertestClient; -export function createStreamsRepositorySupertestClient( - st: supertest.Agent -): StreamsSupertestRepositoryClient { - return getApiClientFromSupertest(st); +export async function createStreamsRepositoryAdminClient( + st: ReturnType +): Promise { + return getAdminApiClient(st); } diff --git a/x-pack/test/api_integration/apis/streams/helpers/requests.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/helpers/requests.ts similarity index 65% rename from x-pack/test/api_integration/apis/streams/helpers/requests.ts rename to x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/helpers/requests.ts index 7ad0fc46444b1..7993d6e002f5c 100644 --- a/x-pack/test/api_integration/apis/streams/helpers/requests.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/helpers/requests.ts @@ -6,7 +6,6 @@ */ import { Client } from '@elastic/elasticsearch'; import { JsonObject } from '@kbn/utility-types'; -import { Agent } from 'supertest'; import expect from '@kbn/expect'; import { SearchTotalHits } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { StreamConfigDefinition } from '@kbn/streams-schema'; @@ -75,33 +74,3 @@ export async function putStream( .expect(expectStatusCode) .then((response) => response.body); } - -export async function getStream(supertest: Agent, name: string) { - const req = supertest.get(`/api/streams/${encodeURIComponent(name)}`).set('kbn-xsrf', 'xxx'); - const response = await req.send().expect(200); - return response.body; -} - -export async function listStreams(supertest: Agent) { - const req = supertest.get(`/api/streams`).set('kbn-xsrf', 'xxx'); - const response = await req.send().expect(200); - return response.body; -} - -export async function deleteStream(supertest: Agent, id: string) { - const req = supertest.delete(`/api/streams/${id}`).set('kbn-xsrf', 'xxx'); - const response = await req.send().expect(200); - return response.body; -} - -export async function getUnmappedFieldsForStream(supertest: Agent, id: string) { - const req = supertest.get(`/api/streams/${id}/schema/unmapped_fields`).set('kbn-xsrf', 'xxx'); - const response = await req.send().expect(200); - return response.body; -} - -export async function simulateFieldsForStream(supertest: Agent, id: string, body: JsonObject) { - const req = supertest.post(`/api/streams/${id}/schema/fields_simulation`).set('kbn-xsrf', 'xxx'); - const response = await req.send(body).expect(200); - return response.body; -} diff --git a/x-pack/test/api_integration/apis/streams/index.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/index.ts similarity index 73% rename from x-pack/test/api_integration/apis/streams/index.ts rename to x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/index.ts index f481bfcf03639..5f685bad1684b 100644 --- a/x-pack/test/api_integration/apis/streams/index.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/index.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { FtrProviderContext } from '../../ftr_provider_context'; +import type { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context'; -export default function ({ loadTestFile }: FtrProviderContext) { +export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext) { describe('Streams Endpoints', () => { loadTestFile(require.resolve('./full_flow')); loadTestFile(require.resolve('./enrichment')); @@ -15,6 +15,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./flush_config')); loadTestFile(require.resolve('./assets/dashboard')); loadTestFile(require.resolve('./schema')); + loadTestFile(require.resolve('./processing_simulate')); loadTestFile(require.resolve('./root_stream')); }); } diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/processing_simulate.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/processing_simulate.ts new file mode 100644 index 0000000000000..f2afc4f9b9bb4 --- /dev/null +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/processing_simulate.ts @@ -0,0 +1,239 @@ +/* + * 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 expect from '@kbn/expect'; +import { ClientRequestParamsOf } from '@kbn/server-route-repository-utils'; +import { StreamsRouteRepository } from '@kbn/streams-plugin/server'; +import { errors } from '@elastic/elasticsearch'; +import { disableStreams, enableStreams, forkStream, indexDocument } from './helpers/requests'; +import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context'; +import { + StreamsSupertestRepositoryClient, + createStreamsRepositoryAdminClient, +} from './helpers/repository_client'; + +async function simulateProcessingForStream( + client: StreamsSupertestRepositoryClient, + id: string, + body: ClientRequestParamsOf< + StreamsRouteRepository, + 'POST /api/streams/{id}/processing/_simulate' + >['params']['body'], + statusCode = 200 +) { + return client + .fetch('POST /api/streams/{id}/processing/_simulate', { + params: { + path: { id }, + body, + }, + }) + .expect(statusCode); +} + +export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { + const roleScopedSupertest = getService('roleScopedSupertest'); + const esClient = getService('es'); + + let apiClient: StreamsSupertestRepositoryClient; + + describe('Processing Simulation', () => { + const TEST_TIMESTAMP = '2025-01-01T00:00:10.000Z'; + const TEST_MESSAGE = `${TEST_TIMESTAMP} error test`; + const TEST_HOST = 'test-host'; + + const testDoc = { + '@timestamp': TEST_TIMESTAMP, + message: TEST_MESSAGE, + 'host.name': TEST_HOST, + 'log.level': 'error', + }; + + const basicGrokProcessor = { + config: { + grok: { + field: 'message', + patterns: [ + '%{TIMESTAMP_ISO8601:parsed_timestamp} %{LOGLEVEL:parsed_level} %{GREEDYDATA:parsed_message}', + ], + }, + }, + }; + + const createTestDocument = (message = TEST_MESSAGE) => ({ + '@timestamp': TEST_TIMESTAMP, + message, + }); + + before(async () => { + apiClient = await createStreamsRepositoryAdminClient(roleScopedSupertest); + + await enableStreams(apiClient); + + // Create a test document + await indexDocument(esClient, 'logs', testDoc); + + // Create a forked stream for testing + await forkStream(apiClient, 'logs', { + stream: { + name: 'logs.test', + }, + condition: { + field: 'host.name', + operator: 'eq' as const, + value: TEST_HOST, + }, + }); + }); + + after(async () => { + await disableStreams(apiClient); + }); + + describe('Successful simulations', () => { + describe('with valid documents', () => { + it('should simulate additive processing', async () => { + const response = await simulateProcessingForStream(apiClient, 'logs.test', { + processing: [basicGrokProcessor], + documents: [createTestDocument()], + }); + + expect(response.body.success_rate).to.be(1); + expect(response.body.failure_rate).to.be(0); + + const { isMatch, value } = response.body.documents[0]; + expect(isMatch).to.be(true); + expect(value).to.have.property('parsed_timestamp', TEST_TIMESTAMP); + expect(value).to.have.property('parsed_level', 'error'); + expect(value).to.have.property('parsed_message', 'test'); + }); + + it('should simulate with detected fields', async () => { + const response = await simulateProcessingForStream(apiClient, 'logs.test', { + processing: [basicGrokProcessor], + documents: [createTestDocument()], + detected_fields: [ + { name: 'parsed_timestamp', type: 'date' }, + { name: 'parsed_level', type: 'keyword' }, + ], + }); + + const findField = (name: string) => + response.body.detected_fields.find((f: { name: string }) => f.name === name); + + expect(response.body.detected_fields).to.have.length(3); // Including parsed_message + expect(findField('parsed_timestamp')).to.have.property('type', 'date'); + expect(findField('parsed_level')).to.have.property('type', 'keyword'); + }); + }); + + describe('with mixed success/failure documents', () => { + it('should provide accurate success/failure rates', async () => { + const response = await simulateProcessingForStream(apiClient, 'logs.test', { + processing: [basicGrokProcessor], + documents: [ + createTestDocument(), + createTestDocument('invalid format'), + createTestDocument(`${TEST_TIMESTAMP} info test`), + ], + }); + + expect(response.body.success_rate).to.be(0.67); + expect(response.body.failure_rate).to.be(0.33); + expect(response.body.documents).to.have.length(3); + expect(response.body.documents[0].isMatch).to.be(true); + expect(response.body.documents[1].isMatch).to.be(false); + expect(response.body.documents[2].isMatch).to.be(true); + }); + }); + }); + + describe('Failed simulations', () => { + it('should fail with invalid processor configurations', async () => { + await simulateProcessingForStream( + apiClient, + 'logs.test', + { + processing: [ + { + config: { + grok: { + field: 'message', + patterns: ['%{INVALID_PATTERN:field}'], + }, + }, + }, + ], + documents: [createTestDocument('test message')], + }, + 400 + ); + }); + + it('should fail when attempting to update existing fields', async () => { + const response = await simulateProcessingForStream( + apiClient, + 'logs.test', + { + processing: [ + { + config: { + grok: { + field: 'message', + patterns: ['%{TIMESTAMP_ISO8601:parsed_timestamp} %{GREEDYDATA:message}'], // Overwrites existing message field + }, + }, + }, + ], + documents: [createTestDocument(`${TEST_TIMESTAMP} original message`)], + }, + 400 + ); + + expect((response.body as errors.ResponseError['body']).message).to.contain( + 'The processor is not additive to the documents. It might update fields [message]' + ); + }); + + it('should fail with incompatible detected field mappings', async () => { + const response = await simulateProcessingForStream( + apiClient, + 'logs.test', + { + processing: [basicGrokProcessor], + documents: [createTestDocument()], + detected_fields: [ + { name: 'parsed_timestamp', type: 'boolean' }, // Incompatible type + ], + }, + 400 + ); + + expect((response.body as errors.ResponseError['body']).message).to.contain( + 'The detected field types might not be compatible with these documents.' + ); + }); + }); + + describe('Partial success simulations', () => { + it('should handle mixed success/failure documents', async () => { + const response = await simulateProcessingForStream(apiClient, 'logs.test', { + processing: [basicGrokProcessor], + documents: [ + createTestDocument(), // Will succeed + createTestDocument('invalid format'), // Will fail + ], + }); + + expect(response.body.success_rate).to.be(0.5); + expect(response.body.failure_rate).to.be(0.5); + expect(response.body.documents[0].isMatch).to.be(true); + expect(response.body.documents[1].isMatch).to.be(false); + }); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/streams/root_stream.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/root_stream.ts similarity index 86% rename from x-pack/test/api_integration/apis/streams/root_stream.ts rename to x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/root_stream.ts index fe26439b1bb43..7d4c130f84124 100644 --- a/x-pack/test/api_integration/apis/streams/root_stream.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/root_stream.ts @@ -7,9 +7,12 @@ import expect from '@kbn/expect'; import { WiredStreamConfigDefinition, WiredStreamDefinition } from '@kbn/streams-schema'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context'; import { disableStreams, enableStreams, putStream } from './helpers/requests'; -import { createStreamsRepositorySupertestClient } from './helpers/repository_client'; +import { + StreamsSupertestRepositoryClient, + createStreamsRepositoryAdminClient, +} from './helpers/repository_client'; const rootStreamDefinition: WiredStreamDefinition = { name: 'logs', @@ -37,12 +40,13 @@ const rootStreamDefinition: WiredStreamDefinition = { }, }; -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const apiClient = createStreamsRepositorySupertestClient(supertest); +export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { + const roleScopedSupertest = getService('roleScopedSupertest'); + let apiClient: StreamsSupertestRepositoryClient; describe('Root stream', () => { before(async () => { + apiClient = await createStreamsRepositoryAdminClient(roleScopedSupertest); await enableStreams(apiClient); }); diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/schema.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/schema.ts new file mode 100644 index 0000000000000..7f5053ff76ae2 --- /dev/null +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/schema.ts @@ -0,0 +1,121 @@ +/* + * 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 expect from '@kbn/expect'; +import { disableStreams, enableStreams, forkStream, indexDocument } from './helpers/requests'; +import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context'; +import { + StreamsSupertestRepositoryClient, + createStreamsRepositoryAdminClient, +} from './helpers/repository_client'; + +export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { + const roleScopedSupertest = getService('roleScopedSupertest'); + const esClient = getService('es'); + + let apiClient: StreamsSupertestRepositoryClient; + + describe('Streams Schema', () => { + before(async () => { + apiClient = await createStreamsRepositoryAdminClient(roleScopedSupertest); + await enableStreams(apiClient); + + const doc = { + '@timestamp': '2024-01-01T00:00:10.000Z', + message: '2023-01-01T00:00:10.000Z error test', + ['some.field']: 'some value', + ['another.field']: 'another value', + lastField: 'last value', + ['log.level']: 'warning', + }; + + await indexDocument(esClient, 'logs', doc); + }); + + after(async () => { + await disableStreams(apiClient); + }); + + describe('Unmapped fields API', () => { + it('Returns unmapped fields', async () => { + const response = await apiClient + .fetch('GET /api/streams/{id}/schema/unmapped_fields', { + params: { + path: { + id: 'logs', + }, + }, + }) + .expect(200); + expect(response.body.unmappedFields).to.eql(['another.field', 'lastField', 'some.field']); + }); + }); + + describe('Fields simulation API', () => { + it('Returns failure status when simulation would fail', async () => { + const response = await apiClient.fetch('POST /api/streams/{id}/schema/fields_simulation', { + params: { + path: { + id: 'logs', + }, + body: { + field_definitions: [{ name: 'message', type: 'boolean' }], + }, + }, + }); + + expect(response.body.status).to.be('failure'); + expect(response.body.simulationError).to.be.a('string'); + expect(response.body.documentsWithRuntimeFieldsApplied).to.be(null); + }); + it('Returns success status when simulation would succeed', async () => { + const response = await apiClient.fetch('POST /api/streams/{id}/schema/fields_simulation', { + params: { + path: { + id: 'logs', + }, + body: { + field_definitions: [{ name: 'message', type: 'keyword' }], + }, + }, + }); + + expect(response.body.status).to.be('success'); + expect(response.body.simulationError).to.be(null); + expect(response.body.documentsWithRuntimeFieldsApplied).length(1); + }); + it('Returns unknown status when documents are missing and status cannot be determined', async () => { + const forkBody = { + stream: { + name: 'logs.nginx', + }, + condition: { + field: 'log.logger', + operator: 'eq' as const, + value: 'nginx', + }, + }; + + await forkStream(apiClient, 'logs', forkBody); + const response = await apiClient.fetch('POST /api/streams/{id}/schema/fields_simulation', { + params: { + path: { + id: 'logs.nginx', + }, + body: { + field_definitions: [{ name: 'message', type: 'keyword' }], + }, + }, + }); + + expect(response.body.status).to.be('unknown'); + expect(response.body.simulationError).to.be(null); + expect(response.body.documentsWithRuntimeFieldsApplied).to.be(null); + }); + }); + }); +} diff --git a/x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.index.ts b/x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.index.ts index edd82fc62dca6..bf722be7b391e 100644 --- a/x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.index.ts +++ b/x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.index.ts @@ -22,5 +22,6 @@ export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext) loadTestFile(require.resolve('../../apis/observability/slo')); loadTestFile(require.resolve('../../apis/observability/synthetics')); loadTestFile(require.resolve('../../apis/observability/ai_assistant')); + loadTestFile(require.resolve('../../apis/observability/streams')); }); } diff --git a/x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.index.ts b/x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.index.ts index 4f0c42e12b1fb..3ac428860a588 100644 --- a/x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.index.ts +++ b/x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.index.ts @@ -16,5 +16,6 @@ export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext) loadTestFile(require.resolve('../../apis/observability/synthetics')); loadTestFile(require.resolve('../../apis/observability/infra')); loadTestFile(require.resolve('../../apis/observability/ai_assistant')); + loadTestFile(require.resolve('../../apis/observability/streams')); }); } diff --git a/x-pack/test/api_integration/services/security_solution_api.gen.ts b/x-pack/test/api_integration/services/security_solution_api.gen.ts index 4e9c66324cb26..a069b2e1134ce 100644 --- a/x-pack/test/api_integration/services/security_solution_api.gen.ts +++ b/x-pack/test/api_integration/services/security_solution_api.gen.ts @@ -123,7 +123,6 @@ import { InstallMigrationRulesRequestBodyInput, } from '@kbn/security-solution-plugin/common/siem_migrations/model/api/rules/rule_migration.gen'; import { InstallPrepackedTimelinesRequestBodyInput } from '@kbn/security-solution-plugin/common/api/timeline/install_prepackaged_timelines/install_prepackaged_timelines_route.gen'; -import { InstallTranslatedMigrationRulesRequestParamsInput } from '@kbn/security-solution-plugin/common/siem_migrations/model/api/rules/rule_migration.gen'; import { ListEntitiesRequestQueryInput } from '@kbn/security-solution-plugin/common/api/entity_analytics/entity_store/entities/list_entities.gen'; import { PatchRuleRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/crud/patch_rule/patch_rule_route.gen'; import { PatchTimelineRequestBodyInput } from '@kbn/security-solution-plugin/common/api/timeline/patch_timelines/patch_timeline_route.gen'; @@ -1208,27 +1207,6 @@ finalize it. .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send(props.body as object); }, - /** - * Installs all translated migration rules - */ - installTranslatedMigrationRules( - props: InstallTranslatedMigrationRulesProps, - kibanaSpace: string = 'default' - ) { - return supertest - .post( - routeWithNamespace( - replaceParams( - '/internal/siem_migrations/rules/{migration_id}/install_translated', - props.params - ), - kibanaSpace - ) - ) - .set('kbn-xsrf', 'true') - .set(ELASTIC_HTTP_VERSION_HEADER, '1') - .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana'); - }, internalUploadAssetCriticalityRecords(kibanaSpace: string = 'default') { return supertest .post(routeWithNamespace('/internal/asset_criticality/upload_csv', kibanaSpace)) @@ -1860,9 +1838,6 @@ export interface InstallMigrationRulesProps { export interface InstallPrepackedTimelinesProps { body: InstallPrepackedTimelinesRequestBodyInput; } -export interface InstallTranslatedMigrationRulesProps { - params: InstallTranslatedMigrationRulesRequestParamsInput; -} export interface ListEntitiesProps { query: ListEntitiesRequestQueryInput; } diff --git a/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/breakdown.spec.snap b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/breakdown.spec.snap index 68495907b3c7f..a9d6cda42a565 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/breakdown.spec.snap +++ b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/breakdown.spec.snap @@ -4,7 +4,6 @@ exports[`APM API tests transactions/breakdown.spec.ts basic apm_8.0.0 Breakdown Object { "timeseries": Array [ Object { - "color": "#54b399", "data": Array [ Object { "x": 1627973400000, @@ -257,7 +256,6 @@ Object { "type": "areaStacked", }, Object { - "color": "#6092c0", "data": Array [ Object { "x": 1627973400000, @@ -510,7 +508,6 @@ Object { "type": "areaStacked", }, Object { - "color": "#d36086", "data": Array [ Object { "x": 1627973400000, @@ -763,7 +760,6 @@ Object { "type": "areaStacked", }, Object { - "color": "#9170b8", "data": Array [ Object { "x": 1627973400000, @@ -1019,7 +1015,7 @@ Object { } `; -exports[`APM API tests transactions/breakdown.spec.ts basic apm_8.0.0 Breakdown when data is loaded returns the transaction breakdown for a transaction group 9`] = ` +exports[`APM API tests transactions/breakdown.spec.ts basic apm_8.0.0 Breakdown when data is loaded returns the transaction breakdown for a transaction group 8`] = ` Array [ Object { "x": 1627973400000, diff --git a/x-pack/test/apm_api_integration/tests/transactions/breakdown.spec.ts b/x-pack/test/apm_api_integration/tests/transactions/breakdown.spec.ts index d7cd6d5b87779..db0f8e0b846a7 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/breakdown.spec.ts +++ b/x-pack/test/apm_api_integration/tests/transactions/breakdown.spec.ts @@ -64,7 +64,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { expectSnapshot(numberOfSeries).toMatchInline(`1`); - const { title, color, type, data, hideLegend, legendValue } = timeseries[0]; + const { title, type, data, hideLegend, legendValue } = timeseries[0]; const nonNullDataPoints = data.filter(({ y }: { y: number | null }) => y !== null); @@ -103,7 +103,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { `); expectSnapshot(title).toMatchInline(`"app"`); - expectSnapshot(color).toMatchInline(`"#54b399"`); expectSnapshot(type).toMatchInline(`"areaStacked"`); expectSnapshot(hideLegend).toMatchInline(`false`); expectSnapshot(legendValue).toMatchInline(`"100%"`); diff --git a/x-pack/test/cases_api_integration/common/lib/alerts.ts b/x-pack/test/cases_api_integration/common/lib/alerts.ts index 8df074b0d3474..48f6540b60b81 100644 --- a/x-pack/test/cases_api_integration/common/lib/alerts.ts +++ b/x-pack/test/cases_api_integration/common/lib/alerts.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import type SuperTest from 'supertest'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { ToolingLog } from '@kbn/tooling-log'; import { DETECTION_ENGINE_QUERY_SIGNALS_URL } from '@kbn/security-solution-plugin/common/constants'; import { DetectionAlert } from '@kbn/security-solution-plugin/common/api/detection_engine'; diff --git a/x-pack/test/cases_api_integration/common/lib/api/index.ts b/x-pack/test/cases_api_integration/common/lib/api/index.ts index 5b174cc406f60..81f2514697689 100644 --- a/x-pack/test/cases_api_integration/common/lib/api/index.ts +++ b/x-pack/test/cases_api_integration/common/lib/api/index.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import type { TransportResult } from '@elastic/elasticsearch'; import type { Client } from '@elastic/elasticsearch'; import { GetResponse } from '@elastic/elasticsearch/lib/api/types'; @@ -53,11 +53,14 @@ import { GetRelatedCasesByAlertResponse, SimilarCasesSearchRequest, CasesSimilarResponse, + UserActionFindRequest, + UserActionInternalFindResponse, } from '@kbn/cases-plugin/common/types/api'; import { getCaseCreateObservableUrl, getCaseUpdateObservableUrl, getCaseDeleteObservableUrl, + getCaseFindUserActionsUrl, } from '@kbn/cases-plugin/common/api'; import { User } from '../authentication/types'; import { superUser } from '../authentication/users'; @@ -975,3 +978,25 @@ export const similarCases = async ({ return res; }; + +export const findInternalCaseUserActions = async ({ + supertest, + caseID, + options = {}, + expectedHttpCode = 200, + auth = { user: superUser, space: null }, +}: { + supertest: SuperTest.Agent; + caseID: string; + options?: UserActionFindRequest; + expectedHttpCode?: number; + auth?: { user: User; space: string | null }; +}): Promise => { + const { body: userActions } = await supertest + .get(`${getSpaceUrlPrefix(auth.space)}${getCaseFindUserActionsUrl(caseID)}`) + .query(options) + .auth(auth.user.username, auth.user.password) + .expect(expectedHttpCode); + + return userActions; +}; diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/index.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/index.ts index 6378ce936e9ea..f348278187bf9 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/index.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/index.ts @@ -58,6 +58,7 @@ export default ({ loadTestFile }: FtrProviderContext): void => { loadTestFile(require.resolve('./internal/bulk_delete_file_attachments')); loadTestFile(require.resolve('./internal/search_cases')); loadTestFile(require.resolve('./internal/replace_custom_field')); + loadTestFile(require.resolve('./internal/find_user_actions.ts')); /** * Attachments framework diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/find_user_actions.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/find_user_actions.ts new file mode 100644 index 0000000000000..f4926eda9ac9e --- /dev/null +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/find_user_actions.ts @@ -0,0 +1,1006 @@ +/* + * 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 expect from '@kbn/expect'; +import { + AttachmentType, + Case, + CaseSeverity, + CaseStatuses, +} from '@kbn/cases-plugin/common/types/domain'; +import { MAX_USER_ACTIONS_PER_PAGE } from '@kbn/cases-plugin/common/constants'; +import { + UserActionTypes, + CommentUserAction, + ConnectorTypes, +} from '@kbn/cases-plugin/common/types/domain'; +import { + globalRead, + noKibanaPrivileges, + obsOnly, + obsOnlyRead, + secOnly, + secOnlyRead, + superUser, +} from '../../../../common/lib/authentication/users'; +import { + getPostCaseRequest, + persistableStateAttachment, + postCommentActionsReq, + postCommentAlertReq, + postCommentUserReq, + postExternalReferenceESReq, +} from '../../../../common/lib/mock'; +import { + deleteAllCaseItems, + createCase, + updateCase, + createComment, + bulkCreateAttachments, + findInternalCaseUserActions, + getCaseUserActions, + updateComment, +} from '../../../../common/lib/api'; + +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('find_user_actions (internal)', () => { + afterEach(async () => { + await deleteAllCaseItems(es); + }); + + it('returns the id and version fields but not action_id', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + const allUserActions = await getCaseUserActions({ supertest, caseID: theCase.id }); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + }); + + expect(response.userActions.length).to.be(1); + expect(response.userActions[0].id).not.to.be(undefined); + expect(response.userActions[0].id).to.eql(allUserActions[0].action_id); + expect(response.userActions[0].version).not.to.be(undefined); + expect(response.userActions[0]).not.to.have.property('action_id'); + expect(response.userActions[0]).not.to.have.property('case_id'); + expect(response.latestAttachments.length).to.be(0); + }); + + describe('default parameters', () => { + it('performs a search using the default parameters when no query params are sent', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + await createComment({ + supertest, + caseId: theCase.id, + params: postCommentUserReq, + }); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + }); + + expect(response.userActions.length).to.be(2); + expect(response.latestAttachments.length).to.be(1); + + const createCaseUserAction = response.userActions[0]; + expect(createCaseUserAction.type).to.eql('create_case'); + expect(createCaseUserAction.action).to.eql('create'); + + const commentUserAction = response.userActions[1]; + expect(commentUserAction.type).to.eql('comment'); + expect(commentUserAction.action).to.eql('create'); + + expect(response.page).to.be(1); + expect(response.perPage).to.be(20); + expect(response.total).to.be(2); + }); + + it('should return latest attachments', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + const patchedCase = await createComment({ + supertest, + caseId: theCase.id, + params: postCommentUserReq, + }); + + const newComment = 'this is an edited comment'; + await updateComment({ + supertest, + caseId: theCase.id, + req: { + id: patchedCase.comments![0].id, + version: patchedCase.comments![0].version, + comment: newComment, + type: AttachmentType.user, + owner: 'securitySolutionFixture', + }, + }); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + }); + + expect(response.userActions.length).to.be(3); + expect(response.latestAttachments.length).to.be(1); + + const attachment = response.latestAttachments[0]; + expect(attachment.type).to.eql('user'); + // just to make TS happy + if (attachment.type === 'user') { + expect(attachment.comment).to.eql('this is an edited comment'); + } + expect(attachment.id).to.eql(response.userActions[1].comment_id); + }); + }); + + describe('sorting', () => { + it('sorts the results in descending order by the created_at field', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + await createComment({ + supertest, + caseId: theCase.id, + params: postCommentUserReq, + }); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'desc', + types: [UserActionTypes.comment, UserActionTypes.create_case], + }, + }); + + expect(response.userActions.length).to.be(2); + expect(response.latestAttachments.length).to.be(1); + + const commentUserAction = response.userActions[0]; + expect(commentUserAction.type).to.eql('comment'); + expect(commentUserAction.action).to.eql('create'); + }); + }); + + describe('pagination', () => { + let theCase: Case; + + beforeEach(async () => { + theCase = await createCase(supertest, getPostCaseRequest()); + + await bulkCreateAttachments({ + supertest, + caseId: theCase.id, + params: [postCommentUserReq, postCommentUserReq], + }); + }); + + it('retrieves only 1 user action when perPage is 1', async () => { + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: [UserActionTypes.comment, UserActionTypes.create_case], + perPage: 1, + }, + }); + + expect(response.userActions.length).to.be(1); + expect(response.latestAttachments.length).to.be(0); + + const commentUserAction = response.userActions[0]; + expect(commentUserAction.type).to.eql('create_case'); + expect(commentUserAction.action).to.eql('create'); + }); + + it('retrieves 2 user action when perPage is 2 and there are 3 user actions', async () => { + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: [UserActionTypes.comment, UserActionTypes.create_case], + perPage: 2, + }, + }); + + expect(response.userActions.length).to.be(2); + expect(response.latestAttachments.length).to.be(1); + expect(response.total).to.be(3); + + const createCaseUserAction = response.userActions[0]; + expect(createCaseUserAction.type).to.eql('create_case'); + expect(createCaseUserAction.action).to.eql('create'); + + const commentUserAction = response.userActions[1]; + expect(commentUserAction.type).to.eql('comment'); + expect(commentUserAction.action).to.eql('create'); + }); + + it('retrieves the second page of results', async () => { + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: [UserActionTypes.comment, UserActionTypes.create_case], + page: 2, + perPage: 1, + }, + }); + + expect(response.userActions.length).to.be(1); + expect(response.latestAttachments.length).to.be(1); + expect(response.total).to.be(3); + expect(response.userActions[0].type).to.eql('comment'); + expect(response.userActions[0].action).to.eql('create'); + }); + + it('retrieves the third page of results', async () => { + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: [UserActionTypes.comment, UserActionTypes.create_case], + page: 3, + perPage: 1, + }, + }); + + expect(response.userActions.length).to.be(1); + expect(response.latestAttachments.length).to.be(1); + expect(response.total).to.be(3); + expect(response.userActions[0].type).to.eql('comment'); + expect(response.userActions[0].action).to.eql('create'); + }); + + it('retrieves all the results with a perPage larger than the total', async () => { + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: [UserActionTypes.comment, UserActionTypes.create_case], + page: 1, + perPage: 10, + }, + }); + + expect(response.userActions.length).to.be(3); + expect(response.latestAttachments.length).to.be(2); + expect(response.total).to.be(3); + expect(response.userActions[0].type).to.eql('create_case'); + expect(response.userActions[0].action).to.eql('create'); + }); + + it(`400s when perPage > ${MAX_USER_ACTIONS_PER_PAGE} supplied`, async () => { + await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { perPage: MAX_USER_ACTIONS_PER_PAGE + 1 }, + expectedHttpCode: 400, + }); + }); + + it('400s when trying to fetch more than 10,000 documents', async () => { + await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { page: 209, perPage: 100 }, + expectedHttpCode: 400, + }); + }); + }); + + describe('filters using the type query parameter', () => { + it('returns a 400 when filtering for an invalid type', async () => { + await findInternalCaseUserActions({ + caseID: '123', + supertest, + options: { + sortOrder: 'asc', + // @ts-expect-error using an invalid filter type + types: ['invalid-type'], + }, + expectedHttpCode: 400, + }); + }); + + it('returns an empty array when the user action type does not exist', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: [UserActionTypes.comment], + }, + }); + + expect(response.userActions.length).to.be(0); + expect(response.latestAttachments.length).to.be(0); + }); + + it('retrieves only the comment user actions', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + await createComment({ + supertest, + caseId: theCase.id, + params: postCommentUserReq, + }); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: [UserActionTypes.comment], + }, + }); + + expect(response.userActions.length).to.be(1); + expect(response.latestAttachments.length).to.be(1); + + const commentUserAction = response.userActions[0]; + expect(commentUserAction.type).to.eql('comment'); + expect(commentUserAction.action).to.eql('create'); + expect(commentUserAction.payload).to.eql({ + comment: postCommentUserReq, + }); + }); + + it('retrieves only the connector user actions', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + await updateCase({ + params: { + cases: [ + { + id: theCase.id, + version: theCase.version, + connector: { + id: 'my-jira', + name: 'jira', + type: ConnectorTypes.jira, + fields: { + issueType: 'task', + parent: null, + priority: null, + }, + }, + }, + ], + }, + supertest, + }); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: [UserActionTypes.connector], + }, + }); + + expect(response.userActions.length).to.be(1); + expect(response.latestAttachments.length).to.be(0); + + const updateConnectorUserAction = response.userActions[0]; + expect(updateConnectorUserAction.type).to.eql('connector'); + expect(updateConnectorUserAction.action).to.eql('update'); + expect(updateConnectorUserAction.payload).to.eql({ + connector: { + id: 'my-jira', + name: 'jira', + type: ConnectorTypes.jira, + fields: { + issueType: 'task', + parent: null, + priority: null, + }, + }, + }); + }); + + it('retrieves only the description user actions', async () => { + const newDesc = 'Such a great description'; + const theCase = await createCase(supertest, getPostCaseRequest()); + + await updateCase({ + supertest, + params: { + cases: [ + { + id: theCase.id, + version: theCase.version, + description: newDesc, + }, + ], + }, + }); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: [UserActionTypes.description], + }, + }); + + expect(response.userActions.length).to.be(1); + expect(response.latestAttachments.length).to.be(0); + + const descriptionUserAction = response.userActions[0]; + + expect(descriptionUserAction.type).to.eql('description'); + expect(descriptionUserAction.action).to.eql('update'); + expect(descriptionUserAction.payload).to.eql({ description: newDesc }); + }); + + it('retrieves only the tags user actions', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + await updateCase({ + supertest, + params: { + cases: [ + { + id: theCase.id, + version: theCase.version, + tags: ['cool', 'neat'], + }, + ], + }, + }); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: [UserActionTypes.tags], + }, + }); + + expect(response.userActions.length).to.be(2); + expect(response.latestAttachments.length).to.be(0); + + const addTagsUserAction = response.userActions[0]; + const deleteTagsUserAction = response.userActions[1]; + + expect(addTagsUserAction.type).to.eql('tags'); + expect(addTagsUserAction.action).to.eql('add'); + expect(addTagsUserAction.payload).to.eql({ tags: ['cool', 'neat'] }); + expect(deleteTagsUserAction.type).to.eql('tags'); + expect(deleteTagsUserAction.action).to.eql('delete'); + expect(deleteTagsUserAction.payload).to.eql({ tags: ['defacement'] }); + }); + + it('retrieves only the title user actions', async () => { + const newTitle = 'Such a great title'; + const theCase = await createCase(supertest, getPostCaseRequest()); + + await updateCase({ + supertest, + params: { + cases: [ + { + id: theCase.id, + version: theCase.version, + title: newTitle, + }, + ], + }, + }); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: [UserActionTypes.title], + }, + }); + + expect(response.userActions.length).to.be(1); + expect(response.latestAttachments.length).to.be(0); + + const descriptionUserAction = response.userActions[0]; + + expect(descriptionUserAction.type).to.eql('title'); + expect(descriptionUserAction.action).to.eql('update'); + expect(descriptionUserAction.payload).to.eql({ title: newTitle }); + }); + + it('retrieves only the status user actions', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + await updateCase({ + supertest, + params: { + cases: [ + { + id: theCase.id, + version: theCase.version, + status: CaseStatuses.closed, + }, + ], + }, + }); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: [UserActionTypes.status], + }, + }); + + expect(response.userActions.length).to.be(1); + expect(response.latestAttachments.length).to.be(0); + + const statusUserAction = response.userActions[0]; + + expect(statusUserAction.type).to.eql('status'); + expect(statusUserAction.action).to.eql('update'); + expect(statusUserAction.payload).to.eql({ status: 'closed' }); + }); + + it('retrieves only the settings user actions', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + await updateCase({ + supertest, + params: { + cases: [ + { + id: theCase.id, + version: theCase.version, + settings: { syncAlerts: false }, + }, + ], + }, + }); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: [UserActionTypes.settings], + }, + }); + + expect(response.userActions.length).to.be(1); + expect(response.latestAttachments.length).to.be(0); + + const settingsUserAction = response.userActions[0]; + + expect(settingsUserAction.type).to.eql('settings'); + expect(settingsUserAction.action).to.eql('update'); + expect(settingsUserAction.payload).to.eql({ settings: { syncAlerts: false } }); + }); + + it('retrieves only the severity user actions', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + await updateCase({ + supertest, + params: { + cases: [ + { + id: theCase.id, + version: theCase.version, + severity: CaseSeverity.HIGH, + }, + ], + }, + }); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: [UserActionTypes.severity], + }, + }); + + expect(response.userActions.length).to.be(1); + expect(response.latestAttachments.length).to.be(0); + + const severityUserAction = response.userActions[0]; + + expect(severityUserAction.type).to.eql('severity'); + expect(severityUserAction.action).to.eql('update'); + expect(severityUserAction.payload).to.eql({ severity: CaseSeverity.HIGH }); + }); + + it('retrieves only the create_case user actions', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: [UserActionTypes.create_case], + }, + }); + + expect(response.userActions.length).to.be(1); + expect(response.latestAttachments.length).to.be(0); + + const createCaseUserAction = response.userActions[0]; + + expect(createCaseUserAction.type).to.eql('create_case'); + expect(createCaseUserAction.action).to.eql('create'); + }); + + it('retrieves any non user comment user actions using the action filter', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + const updatedCase = await bulkCreateAttachments({ + supertest, + caseId: theCase.id, + params: [ + postCommentUserReq, + postExternalReferenceESReq, + persistableStateAttachment, + postCommentActionsReq, + ], + }); + + await updateCase({ + supertest, + params: { + cases: [ + { + id: updatedCase.id, + version: updatedCase.version, + severity: CaseSeverity.HIGH, + }, + ], + }, + }); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: ['action'], + }, + }); + + expect(response.userActions.length).to.be(5); + expect(response.latestAttachments.length).to.be(3); + + const createCaseUserAction = response.userActions[0]; + + expect(createCaseUserAction.type).to.eql('create_case'); + expect(createCaseUserAction.action).to.eql('create'); + + const externalRef = response.userActions[1] as CommentUserAction; + + expect(externalRef.type).to.eql('comment'); + expect(externalRef.payload.comment.type).to.eql('externalReference'); + expect(externalRef.action).to.eql('create'); + + const persistableState = response.userActions[2] as CommentUserAction; + + expect(persistableState.type).to.eql('comment'); + expect(persistableState.payload.comment.type).to.eql('persistableState'); + expect(persistableState.action).to.eql('create'); + + const actions = response.userActions[3] as CommentUserAction; + + expect(actions.type).to.eql('comment'); + expect(actions.payload.comment.type).to.eql('actions'); + expect(actions.action).to.eql('create'); + + expect(response.userActions[4].type).to.eql('severity'); + expect(response.userActions[4].action).to.eql('update'); + }); + + it('retrieves only alert user actions', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + await bulkCreateAttachments({ + supertest, + caseId: theCase.id, + params: [postCommentUserReq, postCommentAlertReq], + }); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: ['alert'], + }, + }); + + expect(response.userActions.length).to.be(1); + expect(response.latestAttachments.length).to.be(1); + + const alertUserAction = response.userActions[0] as CommentUserAction; + + expect(alertUserAction.type).to.eql('comment'); + expect(alertUserAction.action).to.eql('create'); + expect(alertUserAction.payload.comment.type).to.eql('alert'); + }); + + it('retrieves only user comment user actions', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + await bulkCreateAttachments({ + supertest, + caseId: theCase.id, + params: [postCommentUserReq, postCommentActionsReq, postCommentAlertReq], + }); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: ['user'], + }, + }); + + expect(response.userActions.length).to.be(1); + expect(response.latestAttachments.length).to.be(1); + + const userCommentUserAction = response.userActions[0] as CommentUserAction; + + expect(userCommentUserAction.type).to.eql('comment'); + expect(userCommentUserAction.action).to.eql('create'); + expect(userCommentUserAction.payload.comment.type).to.eql('user'); + }); + + it('retrieves attachment user actions', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + await bulkCreateAttachments({ + supertest, + caseId: theCase.id, + params: [ + // This one should not show up in the filter for attachments + postCommentUserReq, + postExternalReferenceESReq, + persistableStateAttachment, + // This one should not show up in the filter for attachments + postCommentActionsReq, + // This one should not show up in the filter for attachments + postCommentAlertReq, + ], + }); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: ['attachment'], + }, + }); + + expect(response.userActions.length).to.be(2); + expect(response.latestAttachments.length).to.be(2); + + const externalRefUserAction = response.userActions[0] as CommentUserAction; + + expect(externalRefUserAction.type).to.eql('comment'); + expect(externalRefUserAction.action).to.eql('create'); + expect(externalRefUserAction.payload.comment.type).to.eql('externalReference'); + + const peristableStateUserAction = response.userActions[1] as CommentUserAction; + + expect(peristableStateUserAction.type).to.eql('comment'); + expect(peristableStateUserAction.action).to.eql('create'); + expect(peristableStateUserAction.payload.comment.type).to.eql('persistableState'); + }); + + describe('filtering on multiple types', () => { + it('retrieves the create_case and comment user actions', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + await createComment({ + supertest, + caseId: theCase.id, + params: postCommentUserReq, + }); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: [UserActionTypes.create_case, UserActionTypes.comment], + }, + }); + + expect(response.userActions.length).to.be(2); + expect(response.latestAttachments.length).to.be(1); + + const createCaseUserAction = response.userActions[0]; + expect(createCaseUserAction.type).to.eql('create_case'); + expect(createCaseUserAction.action).to.eql('create'); + + const commentUserAction = response.userActions[1]; + expect(commentUserAction.type).to.eql('comment'); + expect(commentUserAction.action).to.eql('create'); + }); + + it('retrieves the create_case user action when there are not valid comment user actions', async () => { + const theCase = await createCase(supertest, getPostCaseRequest()); + + const response = await findInternalCaseUserActions({ + caseID: theCase.id, + supertest, + options: { + sortOrder: 'asc', + types: [UserActionTypes.create_case, UserActionTypes.comment], + }, + }); + + expect(response.userActions.length).to.be(1); + expect(response.latestAttachments.length).to.be(0); + + const createCaseUserAction = response.userActions[0]; + expect(createCaseUserAction.type).to.eql('create_case'); + expect(createCaseUserAction.action).to.eql('create'); + }); + }); + + describe('rbac', () => { + const supertestWithoutAuth = getService('supertestWithoutAuth'); + + let secCase: Case; + let obsCase: Case; + let secCaseSpace2: Case; + + beforeEach(async () => { + [secCase, obsCase, secCaseSpace2] = await Promise.all([ + createCase( + supertestWithoutAuth, + getPostCaseRequest({ owner: 'securitySolutionFixture' }), + 200, + { + user: secOnly, + space: 'space1', + } + ), + createCase( + supertestWithoutAuth, + getPostCaseRequest({ owner: 'observabilityFixture' }), + 200, + { + user: obsOnly, + space: 'space1', + } + ), + createCase( + supertestWithoutAuth, + getPostCaseRequest({ owner: 'securitySolutionFixture' }), + 200, + { + user: superUser, + space: 'space2', + } + ), + ]); + }); + + it('should return with the correct status code when executing with various users', async () => { + for (const scenario of [ + { + user: globalRead, + id: secCase.id, + space: 'space1', + }, + { + user: globalRead, + id: obsCase.id, + space: 'space1', + }, + { + user: superUser, + id: secCase.id, + space: 'space1', + }, + { + user: superUser, + id: obsCase.id, + space: 'space1', + }, + { + user: secOnlyRead, + id: secCase.id, + space: 'space1', + }, + { + user: obsOnlyRead, + id: obsCase.id, + space: 'space1', + }, + ]) { + const res = await findInternalCaseUserActions({ + caseID: scenario.id, + supertest: supertestWithoutAuth, + options: { + sortOrder: 'asc', + types: [UserActionTypes.create_case], + }, + auth: { user: scenario.user, space: scenario.space }, + }); + + expect(res.userActions.length).to.be(1); + } + }); + + it('should fail to find user actions for a case that the user is not authorized for', async () => { + for (const scenario of [ + { + user: secOnlyRead, + id: obsCase.id, + space: 'space1', + expectedCode: 403, + }, + { + user: obsOnlyRead, + id: secCase.id, + space: 'space1', + expectedCode: 403, + }, + { + user: noKibanaPrivileges, + id: secCase.id, + space: 'space1', + expectedCode: 403, + }, + { + user: secOnlyRead, + id: secCaseSpace2.id, + space: 'space2', + expectedCode: 403, + }, + ]) { + await findInternalCaseUserActions({ + caseID: scenario.id, + supertest: supertestWithoutAuth, + expectedHttpCode: scenario.expectedCode, + options: { + sortOrder: 'asc', + types: [UserActionTypes.create_case], + }, + auth: { user: scenario.user, space: scenario.space }, + }); + } + }); + }); + }); + }); +}; diff --git a/x-pack/test/cloud_security_posture_api/routes/helper/user_roles_utilites.ts b/x-pack/test/cloud_security_posture_api/routes/helper/user_roles_utilites.ts index 2aed6367236e4..14a09c951c5be 100644 --- a/x-pack/test/cloud_security_posture_api/routes/helper/user_roles_utilites.ts +++ b/x-pack/test/cloud_security_posture_api/routes/helper/user_roles_utilites.ts @@ -89,7 +89,7 @@ export function CspSecurityCommonProvider(providerContext: FtrProviderContext) { { base: [], feature: { - siem: ['read'], + siemV2: ['read'], fleet: ['all'], fleetv2: ['all'], savedObjectsManagement: ['all'], @@ -107,7 +107,7 @@ export function CspSecurityCommonProvider(providerContext: FtrProviderContext) { { base: [], feature: { - siem: ['read'], + siemV2: ['read'], fleet: ['all'], fleetv2: ['all'], }, @@ -140,7 +140,7 @@ export function CspSecurityCommonProvider(providerContext: FtrProviderContext) { { base: [], feature: { - siem: ['all'], + siemV2: ['all'], fleet: ['all'], fleetv2: ['all'], savedObjectsManagement: ['all'], diff --git a/x-pack/test/cloud_security_posture_functional/pages/findings_grouping.ts b/x-pack/test/cloud_security_posture_functional/pages/findings_grouping.ts index c918fb275d968..c904e1b45f2c1 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/findings_grouping.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/findings_grouping.ts @@ -296,14 +296,14 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { } ); }); - it('groups findings by cloud account and sort by compliance score desc', async () => { + it('groups findings by cloud account id and sort by compliance score desc', async () => { const groupSelector = await findings.groupSelector(); await groupSelector.openDropDown(); await groupSelector.setValue('None'); await groupSelector.openDropDown(); - await groupSelector.setValue('Cloud account'); - + await groupSelector.setValue('Cloud account ID'); const grouping = await findings.findingsGrouping(); + const noCloudAccountGroupTitle = 'No cloud account'; const groupCount = await grouping.getGroupCount(); expect(groupCount).to.be('2 cloud accounts'); @@ -314,12 +314,14 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const cloudNameOrder = [ { cloudName: 'Account 2', + cloudId: '2', findingsCount: '1', complianceScore: '0%', benchmarkName: data[3].rule.benchmark.name, }, { cloudName: 'Account 1', + cloudId: '1', findingsCount: '1', complianceScore: '100%', benchmarkName: data[2].rule.benchmark.name, @@ -334,11 +336,15 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await asyncForEach( cloudNameOrder, - async ({ cloudName, complianceScore, findingsCount, benchmarkName }, index) => { + async ({ cloudName, complianceScore, findingsCount, benchmarkName, cloudId }, index) => { const groupRow = await grouping.getRowAtIndex(index); - expect(await groupRow.getVisibleText()).to.contain(cloudName); + const groupTitle = + cloudName === noCloudAccountGroupTitle + ? noCloudAccountGroupTitle + : `${cloudName} - ${cloudId}`; + expect(await groupRow.getVisibleText()).to.contain(groupTitle); - if (cloudName !== 'No cloud account') { + if (cloudName !== noCloudAccountGroupTitle) { expect(await groupRow.getVisibleText()).to.contain(benchmarkName); } @@ -353,36 +359,33 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { } ); }); - it('groups findings by Kubernetes cluster and sort by compliance score desc', async () => { + it('groups findings by Kubernetes cluster id and sort by compliance score desc', async () => { const groupSelector = await findings.groupSelector(); await groupSelector.openDropDown(); await groupSelector.setValue('None'); await groupSelector.openDropDown(); - await groupSelector.setValue('Kubernetes cluster'); + await groupSelector.setValue('Kubernetes cluster ID'); + const noKuberenetsClusterGroupTitle = 'No Kubernetes cluster'; const grouping = await findings.findingsGrouping(); const groupCount = await grouping.getGroupCount(); - expect(groupCount).to.be('2 kubernetes clusters'); + expect(groupCount).to.be('1 kubernetes cluster'); const unitCount = await grouping.getUnitCount(); + expect(unitCount).to.be('4 findings'); const kubernetesOrder = [ { clusterName: 'Cluster 1', - findingsCount: '1', - complianceScore: '0%', + clusterId: '1', + findingsCount: '2', + complianceScore: '50%', benchmarkName: data[0].rule.benchmark.name, }, { - clusterName: 'Cluster 2', - findingsCount: '1', - complianceScore: '100%', - benchmarkName: data[1].rule.benchmark.name, - }, - { - clusterName: 'No Kubernetes cluster', + clusterName: noKuberenetsClusterGroupTitle, findingsCount: '2', complianceScore: '50%', }, @@ -390,12 +393,21 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await asyncForEach( kubernetesOrder, - async ({ clusterName, complianceScore, findingsCount, benchmarkName }, index) => { + async ( + { clusterName, complianceScore, findingsCount, benchmarkName, clusterId }, + index + ) => { const groupRow = await grouping.getRowAtIndex(index); - expect(await groupRow.getVisibleText()).to.contain(clusterName); - if (clusterName !== 'No Kubernetes cluster') { + const groupTitle = + clusterName === noKuberenetsClusterGroupTitle + ? noKuberenetsClusterGroupTitle + : `${clusterName} - ${clusterId}`; + + expect(await groupRow.getVisibleText()).to.contain(groupTitle); + if (clusterName !== noKuberenetsClusterGroupTitle) { expect(await groupRow.getVisibleText()).to.contain(benchmarkName); } + expect( await ( await groupRow.findByTestSubject('cloudSecurityFindingsComplianceScore') diff --git a/x-pack/test/common/utils/server_route_repository/create_supertest_service_from_repository.ts b/x-pack/test/common/utils/server_route_repository/create_admin_service_from_repository.ts similarity index 69% rename from x-pack/test/common/utils/server_route_repository/create_supertest_service_from_repository.ts rename to x-pack/test/common/utils/server_route_repository/create_admin_service_from_repository.ts index 4c0b3da777a1e..1eb0fac391bf4 100644 --- a/x-pack/test/common/utils/server_route_repository/create_supertest_service_from_repository.ts +++ b/x-pack/test/common/utils/server_route_repository/create_admin_service_from_repository.ts @@ -12,10 +12,10 @@ import { ReturnOf, ClientRequestParamsOf, } from '@kbn/server-route-repository'; -import supertest from 'supertest'; import { Subtract, RequiredKeys } from 'utility-types'; -import { format, UrlObject } from 'url'; -import { kbnTestConfig } from '@kbn/test'; +import { format } from 'url'; +import supertest from 'supertest'; +import { RoleScopedSupertestProvider } from '../../../api_integration/deployment_agnostic/services/role_scoped_supertest'; type MaybeOptional> = RequiredKeys extends never ? [TArgs] | [] @@ -44,49 +44,13 @@ type RepositorySupertestReturnOf< }> >; -type ScopedApiClientWithBasicAuthFactory = ( - kibanaServer: UrlObject, - username: string -) => RepositorySupertestClient; - -type ApiClientFromSupertestFactory = ( - st: supertest.Agent -) => RepositorySupertestClient; - -interface RepositorySupertestClientFactory { - getScopedApiClientWithBasicAuth: ScopedApiClientWithBasicAuthFactory; - getApiClientFromSupertest: ApiClientFromSupertestFactory; -} - -export function createSupertestClientFactoryFromRepository< - TServerRouteRepository extends ServerRouteRepository ->(): RepositorySupertestClientFactory { - return { - getScopedApiClientWithBasicAuth: (kibanaServer, username) => { - return getScopedApiClientWithBasicAuth(kibanaServer, username); - }, - getApiClientFromSupertest: (st) => { - return getApiClientFromSupertest(st); - }, - }; -} - -function getScopedApiClientWithBasicAuth( - kibanaServer: UrlObject, - username: string -): RepositorySupertestClient { - const { password } = kbnTestConfig.getUrlParts(); - const baseUrlWithAuth = format({ - ...kibanaServer, - auth: `${username}:${password}`, +export async function getAdminApiClient( + st: ReturnType +): Promise> { + const supertestAdmin = await st.getSupertestWithRoleScope('admin', { + useCookieHeader: true, + withInternalHeaders: true, }); - - return getApiClientFromSupertest(supertest(baseUrlWithAuth)); -} - -export function getApiClientFromSupertest( - st: supertest.Agent -): RepositorySupertestClient { return { fetch: (endpoint, ...rest) => { const options = rest.length ? rest[0] : { type: undefined }; @@ -98,16 +62,19 @@ export function getApiClientFromSupertest = { 'kbn-xsrf': 'foo' }; + const headers: Record = { + 'kbn-xsrf': 'foo', + 'x-elastic-internal-origin': 'kibana', + }; if (version) { headers['Elastic-Api-Version'] = version; } - let res: supertest.Test; + let res: unknown; if (type === 'form-data') { const fields: Array<[string, any]> = Object.entries(params.body); - const formDataRequest = st[method](url) + const formDataRequest = supertestAdmin[method](url) .set(headers) .set('Content-type', 'multipart/form-data'); @@ -117,9 +84,9 @@ export function getApiClientFromSupertest { const security = getService('security'); const testSubjects = getService('testSubjects'); const es = getService('es'); + const browser = getService('browser'); - const INDEX_TEMPLATE_NAME = `test-index-template-name`; + const INDEX_TEMPLATE_NAME = 'index-template-test-name'; describe('Index template tab', function () { before(async () => { @@ -25,59 +26,250 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { // Navigate to the templates tab await pageObjects.indexManagement.changeTabs('templatesTab'); await pageObjects.header.waitUntilLoadingHasFinished(); - // Click create template button - await testSubjects.click('createTemplateButton'); }); afterEach(async () => { - await es.indices.deleteIndexTemplate({ - name: INDEX_TEMPLATE_NAME, + await es.indices.deleteIndexTemplate( + { + name: INDEX_TEMPLATE_NAME, + }, + { ignore: [404] } + ); + + if (await testSubjects.exists('reloadButton')) { + await testSubjects.click('reloadButton'); + } + }); + + describe('index template creation', () => { + beforeEach(async () => { + // Click create template button + await testSubjects.click('createTemplateButton'); + // Complete required fields from step 1 + await testSubjects.setValue('nameField', INDEX_TEMPLATE_NAME); + await testSubjects.setValue('indexPatternsField', 'test-1'); + }); + + afterEach(async () => { + // Click Create template + await pageObjects.indexManagement.clickNextButton(); + // Close detail tab + await testSubjects.click('closeDetailsButton'); + }); + + it('can create an index template with data retention', async () => { + // Enable data retention + await testSubjects.click('dataRetentionToggle > input'); + // Set the retention to 7 hours + await testSubjects.setValue('valueDataRetentionField', '7'); + await testSubjects.click('show-filters-button'); + await testSubjects.click('filter-option-h'); + // Navigate to the last step of the wizard + await testSubjects.click('formWizardStep-5'); + await pageObjects.header.waitUntilLoadingHasFinished(); + + expect(await testSubjects.getVisibleText('lifecycleValue')).to.be('7 hours'); + }); + + it('can create an index template with logsdb index mode', async () => { + // Modify index mode + await testSubjects.click('indexModeField'); + await testSubjects.click('index_mode_logsdb'); + + // Navigate to the last step of the wizard + await testSubjects.click('formWizardStep-5'); + await pageObjects.header.waitUntilLoadingHasFinished(); + + expect(await testSubjects.exists('indexModeTitle')).to.be(true); + expect(await testSubjects.getVisibleText('indexModeValue')).to.be('LogsDB'); }); - await testSubjects.click('reloadButton'); }); - it('can create an index template with data retention', async () => { - // Complete required fields from step 1 - await testSubjects.setValue('nameField', INDEX_TEMPLATE_NAME); - await testSubjects.setValue('indexPatternsField', 'test-1'); - // Enable data retention - await testSubjects.click('dataRetentionToggle > input'); - // Set the retention to 7 hours - await testSubjects.setValue('valueDataRetentionField', '7'); - await testSubjects.click('show-filters-button'); - await testSubjects.click('filter-option-h'); - // Navigate to the last step of the wizard - await testSubjects.click('formWizardStep-5'); - await pageObjects.header.waitUntilLoadingHasFinished(); + describe('index template modification', () => { + beforeEach(async () => { + await es.indices.putIndexTemplate({ + name: INDEX_TEMPLATE_NAME, + index_patterns: ['logsdb-test-index-pattern'], + data_stream: {}, + template: { + settings: { + index: { + mode: 'logsdb', + }, + }, + }, + }); + + await testSubjects.click('reloadButton'); + await pageObjects.indexManagement.clickIndexTemplateNameLink(INDEX_TEMPLATE_NAME); + await testSubjects.click('manageTemplateButton'); + await testSubjects.click('editIndexTemplateButton'); + await pageObjects.header.waitUntilLoadingHasFinished(); + }); + + afterEach(async () => { + if (await testSubjects.exists('closeDetailsButton')) { + // Close Flyout to return to templates tab + await testSubjects.click('closeDetailsButton'); + } else { + // Comeback to templates tab + await pageObjects.common.navigateToApp('indexManagement'); + await pageObjects.indexManagement.changeTabs('templatesTab'); + } + }); + + it('can modify ignore_above, ignore_malformed, ignore_dynamic_beyond_limit, subobjects and timestamp format in an index template with logsdb index mode', async () => { + // Navigate to Index Settings + await testSubjects.click('formWizardStep-2'); + await pageObjects.header.waitUntilLoadingHasFinished(); + + // Modify Index settings + await testSubjects.setValue( + 'kibanaCodeEditor', + JSON.stringify({ + index: { + mapping: { + ignore_above: '20', + total_fields: { + ignore_dynamic_beyond_limit: 'true', + }, + ignore_malformed: 'true', + }, + }, + }), + { + clearWithKeyboard: true, + } + ); - expect(await testSubjects.getVisibleText('lifecycleValue')).to.be('7 hours'); + // Navigate to Mappings + await testSubjects.click('formWizardStep-3'); + await pageObjects.header.waitUntilLoadingHasFinished(); + const mappingTabs = await testSubjects.findAll('formTab'); + await mappingTabs[3].click(); - // Click Create template - await pageObjects.indexManagement.clickNextButton(); - // Close detail tab - await testSubjects.click('closeDetailsButton'); + // Modify timestamp format + await testSubjects.click('comboBoxClearButton'); + await testSubjects.setValue('comboBoxInput', 'basic_date'); + await testSubjects.pressEnter('comboBoxInput'); + + // Modify subobjects + await testSubjects.click('subobjectsToggle'); + + // Navigate to the last step of the wizard + await testSubjects.click('formWizardStep-5'); + await pageObjects.header.waitUntilLoadingHasFinished(); + + // Click Create template + await pageObjects.indexManagement.clickNextButton(); + await pageObjects.header.waitUntilLoadingHasFinished(); + + const flyoutTabs = await testSubjects.findAll('tab'); + + // Verify Index Settings + await flyoutTabs[1].click(); + await pageObjects.header.waitUntilLoadingHasFinished(); + expect(await testSubjects.exists('settingsTabContent')).to.be(true); + const settingsTabContent = await testSubjects.getVisibleText('settingsTabContent'); + expect(JSON.parse(settingsTabContent)).to.eql({ + index: { + mode: 'logsdb', + mapping: { + ignore_above: '20', + total_fields: { + ignore_dynamic_beyond_limit: 'true', + }, + ignore_malformed: 'true', + }, + }, + }); + + // Verify Mappings + await flyoutTabs[2].click(); + await pageObjects.header.waitUntilLoadingHasFinished(); + expect(await testSubjects.exists('mappingsTabContent')).to.be(true); + const mappingsTabContent = await testSubjects.getVisibleText('mappingsTabContent'); + expect(JSON.parse(mappingsTabContent)).to.eql({ + dynamic_date_formats: ['basic_date'], + _source: { + mode: 'synthetic', + }, + subobjects: false, + }); + }); + describe('syntethic source', () => { + it('can not disable syntethic source in an index template with logsdb index mode', async () => { + // Navigate to Mappings + await testSubjects.click('formWizardStep-3'); + await pageObjects.header.waitUntilLoadingHasFinished(); + const mappingTabs = await testSubjects.findAll('formTab'); + await mappingTabs[3].click(); + + // Modify source + await testSubjects.click('sourceValueField'); + await testSubjects.click('disabledSourceFieldOption'); + + // Navigate to the last step of the wizard + await testSubjects.click('formWizardStep-5'); + await pageObjects.header.waitUntilLoadingHasFinished(); + + // Click Create template + await pageObjects.indexManagement.clickNextButton(); + await pageObjects.header.waitUntilLoadingHasFinished(); + + expect(await testSubjects.exists('saveTemplateError')).to.be(true); + + await testSubjects.click('stepReviewPreviewTab'); + await pageObjects.header.waitUntilLoadingHasFinished(); + expect(await testSubjects.exists('simulateTemplatePreview')).to.be(true); + expect(await testSubjects.getVisibleText('simulateTemplatePreview')).to.contain( + '_source can not be disabled in index using [logsdb] index mode' + ); + }); + }); }); - it('can create an index template with logsdb index mode', async () => { - await testSubjects.click('createTemplateButton'); - // Fill out required fields - await testSubjects.setValue('nameField', INDEX_TEMPLATE_NAME); - await testSubjects.setValue('indexPatternsField', 'logsdb-test-index-pattern'); + describe('Index template list', () => { + const TEST_TEMPLATE = 'a_test_template'; + const INDEX_PATTERN = `index_pattern_${Math.random()}`; - await testSubjects.click('indexModeField'); - await testSubjects.click('index_mode_logsdb'); + before(async () => { + await es.indices.putIndexTemplate({ + name: TEST_TEMPLATE, + body: { + index_patterns: [INDEX_PATTERN], + template: { + settings: { + default_pipeline: 'test_pipeline', + }, + }, + }, + }); - // Navigate to the last step of the wizard - await testSubjects.click('formWizardStep-5'); - await pageObjects.header.waitUntilLoadingHasFinished(); + // Navigate to the index management + await pageObjects.common.navigateToApp('indexManagement'); + // Navigate to the templates tab + await pageObjects.indexManagement.changeTabs('templatesTab'); + }); - expect(await testSubjects.exists('indexModeTitle')).to.be(true); - expect(await testSubjects.getVisibleText('indexModeValue')).to.be('LogsDB'); + after(async () => { + await es.indices.deleteIndexTemplate({ name: TEST_TEMPLATE }, { ignore: [404] }); + }); + + it('shows link to ingest pipeline when default pipeline is set', async () => { + // Open details flyout + await pageObjects.indexManagement.clickIndexTemplate(TEST_TEMPLATE); - // Click Create template - await pageObjects.indexManagement.clickNextButton(); - // Close detail tab - await testSubjects.click('closeDetailsButton'); + // Click on the linked ingest pipeline button + const linkedPipelineButton = await testSubjects.find('linkedIngestPipeline'); + await linkedPipelineButton.click(); + + // Expect to navigate to the ingest pipeline page + await pageObjects.header.waitUntilLoadingHasFinished(); + // We should've now navigated to the ingest pipelines app + const currentUrl = await browser.getCurrentUrl(); + expect(currentUrl).to.contain('/ingest/ingest_pipelines/edit/test_pipeline'); + }); }); }); }; diff --git a/x-pack/test/functional/apps/management/feature_controls/management_security.ts b/x-pack/test/functional/apps/management/feature_controls/management_security.ts index 9f73f5500cb4d..248300de7f4a6 100644 --- a/x-pack/test/functional/apps/management/feature_controls/management_security.ts +++ b/x-pack/test/functional/apps/management/feature_controls/management_security.ts @@ -85,7 +85,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { 'objects', 'aiAssistantManagementSelection', 'tags', - 'search_sessions', 'spaces', 'settings', ], diff --git a/x-pack/test/functional/apps/snapshot_restore/snapshot_restore.ts b/x-pack/test/functional/apps/snapshot_restore/snapshot_restore.ts index 875a7aea44ba0..593fd8f910e4b 100644 --- a/x-pack/test/functional/apps/snapshot_restore/snapshot_restore.ts +++ b/x-pack/test/functional/apps/snapshot_restore/snapshot_restore.ts @@ -16,13 +16,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const security = getService('security'); describe('Snapshot restore', function () { + const REPOSITORY = 'my-repository'; before(async () => { await security.testUser.setRoles(['snapshot_restore_user'], { skipBrowserRefresh: true }); await pageObjects.common.navigateToApp('snapshotRestore'); // Create a repository await es.snapshot.createRepository({ - name: 'my-repository', + name: REPOSITORY, verify: true, repository: { type: 'fs', @@ -32,50 +33,275 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }, }, }); + }); + + describe('Snapshot', () => { + before(async () => { + // Create a snapshot + await es.snapshot.create({ + snapshot: 'my-snapshot', + repository: REPOSITORY, + }); + + // Refresh page so that the snapshot shows up in the snapshots table + await browser.refresh(); + }); + + after(async () => { + await es.snapshot.delete({ + snapshot: 'my-snapshot', + repository: REPOSITORY, + }); + }); + + it('Renders the Snapshot restore form', async () => { + await pageObjects.snapshotRestore.refreshWhileSnapshotIsInProgress(); + await pageObjects.header.waitUntilLoadingHasFinished(); + + const snapshots = await pageObjects.snapshotRestore.getSnapshotList(); + + const snapshotRestoreButton = await snapshots[0].snapshotRestore; + // Open the Snapshot restore form + await snapshotRestoreButton.click(); + + // Go to second step (Index settings) + await testSubjects.click('nextButton'); + + // Verify that the Index Settings editor is rendered (uses CodeEditor) + await testSubjects.click('modifyIndexSettingsSwitch'); + expect(await testSubjects.exists('indexSettingsEditor')).to.be(true); + + // Close Index Settings editor + await testSubjects.click('modifyIndexSettingsSwitch'); + + // Go to final step (Review) + await testSubjects.click('nextButton'); + + // Verify that Restore button exists + expect(await testSubjects.exists('restoreButton')).to.be(true); + }); + }); + + describe('Allows to create and restore a snapshot from a Logsdb index', () => { + const logsDbIndex = 'logsdb-index'; + const policyId = 'testPolicy'; + const snapshotPrefx = 'logsdb-snap'; + + before(async () => { + await es.indices.create({ + index: logsDbIndex, + settings: { + mode: 'logsdb', + }, + }); + await pageObjects.common.navigateToApp('snapshotRestore'); + // Create a policy + await pageObjects.snapshotRestore.navToPolicies(); + await pageObjects.snapshotRestore.fillCreateNewPolicyPageOne( + policyId, + `<${snapshotPrefx}-{now/d}>` + ); + await pageObjects.snapshotRestore.fillCreateNewPolicyPageTwo(); + await pageObjects.snapshotRestore.fillCreateNewPolicyPageThree(); + await pageObjects.snapshotRestore.submitNewPolicy(); + await pageObjects.snapshotRestore.closeFlyout(); + }); + + after(async () => { + // Delete the logdb index + await es.indices.delete({ + index: logsDbIndex, + }); + // Delete policy + await es.slm.deleteLifecycle({ + policy_id: policyId, + }); + await es.snapshot.delete({ + snapshot: `${snapshotPrefx}-*`, + repository: REPOSITORY, + }); + await es.indices.delete({ + index: `restored_${logsDbIndex}`, + }); + }); + + it('create snapshot', async () => { + // Verify there are no snapshots + await pageObjects.snapshotRestore.navToSnapshots(); + expect(await testSubjects.exists('emptyPrompt')).to.be(true); - // Create a snapshot - await es.snapshot.create({ - snapshot: 'my-snapshot', - repository: 'my-repository', + // Run policy snapshot + await pageObjects.snapshotRestore.navToPolicies(); + + await pageObjects.snapshotRestore.clickPolicyNameLink(policyId); + await pageObjects.snapshotRestore.clickPolicyActionButton(); + await pageObjects.snapshotRestore.clickRunPolicy(); + await pageObjects.snapshotRestore.clickConfirmationModal(); + await pageObjects.snapshotRestore.closeFlyout(); + + // Open snapshot info flyout + await pageObjects.snapshotRestore.navToSnapshots(false); + await pageObjects.header.waitUntilLoadingHasFinished(); + expect(await testSubjects.exists('snapshotList')).to.be(true); + + await pageObjects.snapshotRestore.refreshWhileSnapshotIsInProgress(); + await pageObjects.header.waitUntilLoadingHasFinished(); + + // Verify that one snapshot has been created + const snapshots = await pageObjects.snapshotRestore.getSnapshotList(); + expect(snapshots.length).to.be(1); + + // Verify that snaphot has been created + const snapshotLink = snapshots[0].snapshotLink; + await snapshotLink.click(); + + // Verify snapshot exists, is complete and contains the logsdb index + expect(await testSubjects.exists('detailTitle')).to.be(true); + expect(await testSubjects.getVisibleText('detailTitle')).to.contain(snapshotPrefx); + expect(await testSubjects.exists('state')).to.be(true); + expect(await testSubjects.getVisibleText('state')).to.contain('Complete'); + await pageObjects.snapshotRestore.clickShowCollapsedIndicesIfPresent(); + expect(await testSubjects.getVisibleText('indices')).to.contain(logsDbIndex); + await pageObjects.snapshotRestore.closeSnaphsotFlyout(); }); - // Wait for snapshot to be ready - await pageObjects.common.sleep(2000); + it('restore snapshot', async () => { + // Verify there are not restore snapshots + await pageObjects.snapshotRestore.navToRestoreStatus(); + await pageObjects.header.waitUntilLoadingHasFinished(); + expect(await testSubjects.exists('noRestoredSnapshotsHeader')).to.be(true); - // Refresh page so that the snapshot shows up in the snapshots table - await browser.refresh(); + // restore snapshot + await pageObjects.snapshotRestore.navToSnapshots(false); + await pageObjects.header.waitUntilLoadingHasFinished(); + + const snapshots = await pageObjects.snapshotRestore.getSnapshotList(); + const snapshotLink = snapshots[0].snapshotLink; + await snapshotLink.click(); + await pageObjects.snapshotRestore.restoreSnapshot(logsDbIndex, true); + + // Verify snapshot has been restored and is complete + await pageObjects.snapshotRestore.navToRestoreStatus(false); + const status = await pageObjects.snapshotRestore.getRestoreStatusList(); + const statusIndex = status[0].index; + const statusIsComplete = status[0].isComplete; + expect(await statusIndex.getVisibleText()).to.be(`restored_${logsDbIndex}`); + expect(await statusIsComplete.getVisibleText()).to.contain('Complete'); + }); }); - it('Renders the Snapshot restore form', async () => { - const snapshots = await pageObjects.snapshotRestore.getSnapshotList(); - const snapshotRestoreButton = await snapshots[0].snapshotRestore; - // Open the Snapshot restore form - await snapshotRestoreButton.click(); + describe('Does not allows to create and restore a source-only snapshot from a Logsdb index', () => { + const sourceOnlyLogsDbIndex = 'sourceonly-logsdb-index'; + const sourceOnlyRepository = 'sourceOnlyRepository'; + const policyId = 'source-only-testPolicy'; + const snapshotPrefx = 'source-only-logsdb-snap'; + before(async () => { + await es.indices.create({ + index: sourceOnlyLogsDbIndex, + settings: { + mode: 'logsdb', + }, + }); + await pageObjects.common.navigateToApp('snapshotRestore'); + // Create a policy + await pageObjects.snapshotRestore.navToPolicies(); + await pageObjects.snapshotRestore.navToRepositories(); + await pageObjects.snapshotRestore.createSourceOnlyRepositoryStepOne(sourceOnlyRepository); + await pageObjects.snapshotRestore.createSourceOnlyRepositoryStepTwo('/tmp/es-backups/'); + await pageObjects.snapshotRestore.closeRepositoriesFlyout(); + + // Create a policy + await pageObjects.snapshotRestore.navToPolicies(); + await pageObjects.snapshotRestore.fillCreateNewPolicyPageOne( + policyId, + `<${snapshotPrefx}-{now/d}>`, + sourceOnlyRepository + ); + await pageObjects.snapshotRestore.fillCreateNewPolicyPageTwo(sourceOnlyLogsDbIndex); + await pageObjects.snapshotRestore.fillCreateNewPolicyPageThree(); + await pageObjects.snapshotRestore.submitNewPolicy(); + await pageObjects.snapshotRestore.closeFlyout(); + }); + + after(async () => { + // Delete the logdb index + await es.indices.delete({ + index: sourceOnlyLogsDbIndex, + }); + // Delete policy + await es.slm.deleteLifecycle({ + policy_id: policyId, + }); + await es.snapshot.delete({ + snapshot: `${snapshotPrefx}-*`, + repository: sourceOnlyRepository, + }); + await es.snapshot.deleteRepository({ + name: sourceOnlyRepository, + }); + }); + + it('creating a snapshot results in a partial state', async () => { + // Verify there are no snapshots + await pageObjects.snapshotRestore.navToSnapshots(); + expect(await testSubjects.exists('emptyPrompt')).to.be(true); + + // Run policy snapshot + await pageObjects.snapshotRestore.navToPolicies(); + + await pageObjects.snapshotRestore.clickPolicyNameLink(policyId); + await pageObjects.snapshotRestore.clickPolicyActionButton(); + await pageObjects.snapshotRestore.clickRunPolicy(); + await pageObjects.snapshotRestore.clickConfirmationModal(); + await pageObjects.snapshotRestore.closeFlyout(); - // Go to second step (Index settings) - await testSubjects.click('nextButton'); + // Open snapshot info flyout + await pageObjects.snapshotRestore.navToSnapshots(false); + await pageObjects.header.waitUntilLoadingHasFinished(); + expect(await testSubjects.exists('snapshotList')).to.be(true); - // Verify that the Index Settings editor is rendered (uses CodeEditor) - await testSubjects.click('modifyIndexSettingsSwitch'); - expect(await testSubjects.exists('indexSettingsEditor')).to.be(true); + await pageObjects.snapshotRestore.refreshWhileSnapshotIsInProgress(); + await pageObjects.header.waitUntilLoadingHasFinished(); - // Close Index Settings editor - await testSubjects.click('modifyIndexSettingsSwitch'); + // Verify that one snapshot has been created + const snapshots = await pageObjects.snapshotRestore.getSnapshotList(); + expect(snapshots.length).to.be(1); - // Go to final step (Review) - await testSubjects.click('nextButton'); + // Verify that snaphot has been created + const snapshotLink = snapshots[0].snapshotLink; + await snapshotLink.click(); - // Verify that Restore button exists - expect(await testSubjects.exists('restoreButton')).to.be(true); + // Verify snapshot exists, is complete and contains the logsdb index + expect(await testSubjects.exists('detailTitle')).to.be(true); + expect(await testSubjects.getVisibleText('detailTitle')).to.contain(snapshotPrefx); + expect(await testSubjects.exists('state')).to.be(true); + expect(await testSubjects.getVisibleText('state')).to.contain('Partial'); + await pageObjects.snapshotRestore.clickShowCollapsedIndicesIfPresent(); + expect(await testSubjects.getVisibleText('indices')).to.contain(sourceOnlyLogsDbIndex); + await pageObjects.snapshotRestore.closeSnaphsotFlyout(); + }); + + it('does not allow to restore snapshot', async () => { + // restore snapshot + await pageObjects.snapshotRestore.navToSnapshots(false); + await pageObjects.header.waitUntilLoadingHasFinished(); + + const snapshots = await pageObjects.snapshotRestore.getSnapshotList(); + const snapshotLink = snapshots[0].snapshotLink; + await snapshotLink.click(); + await pageObjects.snapshotRestore.restoreSnapshot(sourceOnlyLogsDbIndex, true); + + // Verify it returns an error and doesn't allow to restore snapshot + expect(await testSubjects.exists('restoreSnapshotError')).to.be(true); + expect(await testSubjects.getVisibleText('restoreSnapshotError')).to.contain( + `index [${sourceOnlyLogsDbIndex}] wasn't fully snapshotted - cannot restore` + ); + }); }); after(async () => { - await es.snapshot.delete({ - snapshot: 'my-snapshot', - repository: 'my-repository', - }); await es.snapshot.deleteRepository({ - name: 'my-repository', + name: REPOSITORY, }); await security.testUser.restoreDefaults(); }); diff --git a/x-pack/test/functional/config.base.js b/x-pack/test/functional/config.base.js index 3904458ff4772..5785ff0f0aea0 100644 --- a/x-pack/test/functional/config.base.js +++ b/x-pack/test/functional/config.base.js @@ -623,6 +623,13 @@ export default async function ({ readConfigFile }) { 'manage_slm', 'cluster:admin/snapshot', 'cluster:admin/repository', + 'manage_index_templates', + ], + indices: [ + { + names: ['*'], + privileges: ['all'], + }, ], }, kibana: [ diff --git a/x-pack/test/functional/page_objects/dataset_quality.ts b/x-pack/test/functional/page_objects/dataset_quality.ts index 47a9261c906f7..9a116ad3e8a4d 100644 --- a/x-pack/test/functional/page_objects/dataset_quality.ts +++ b/x-pack/test/functional/page_objects/dataset_quality.ts @@ -198,7 +198,9 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv }, async waitUntilSummaryPanelLoaded(isStateful: boolean = true) { - await testSubjects.missingOrFail(`datasetQuality-${texts.activeDatasets}-loading`); + await testSubjects.missingOrFail(`datasetQuality-${texts.activeDatasets}-loading`, { + timeout: 5 * 1000, // Increasing timeout since tests were flaky + }); if (isStateful) { await testSubjects.missingOrFail(`datasetQuality-${texts.estimatedData}-loading`); } diff --git a/x-pack/test/functional/page_objects/index_management_page.ts b/x-pack/test/functional/page_objects/index_management_page.ts index a29e84e677cbc..5b9da3bd54906 100644 --- a/x-pack/test/functional/page_objects/index_management_page.ts +++ b/x-pack/test/functional/page_objects/index_management_page.ts @@ -38,6 +38,17 @@ export function IndexManagementPageProvider({ getService }: FtrProviderContext) await policyDetailsLinks[indexOfRow].click(); }, + async clickIndexTemplate(name: string): Promise { + const indexTemplateLinks = await testSubjects.findAll('templateDetailsLink'); + + for (const link of indexTemplateLinks) { + if ((await link.getVisibleText()).includes(name)) { + await link.click(); + return; + } + } + }, + async clickBulkEditDataRetention(dataStreamNames: string[]): Promise { for (const dsName of dataStreamNames) { const checkbox = await testSubjects.find(`checkboxSelectRow-${dsName}`); diff --git a/x-pack/test/functional/page_objects/search_index_details_page.ts b/x-pack/test/functional/page_objects/search_index_details_page.ts index feef7eb157172..c6afabfa25569 100644 --- a/x-pack/test/functional/page_objects/search_index_details_page.ts +++ b/x-pack/test/functional/page_objects/search_index_details_page.ts @@ -233,20 +233,6 @@ export function SearchIndexDetailPageProvider({ getService }: FtrProviderContext ); }, - async expectSampleDocumentsWithCustomMappings() { - await browser.refresh(); - await testSubjects.existOrFail('ingestDataCodeExample-code-block'); - expect(await testSubjects.getVisibleText('ingestDataCodeExample-code-block')).to.contain( - 'Example text 1' - ); - expect(await testSubjects.getVisibleText('ingestDataCodeExample-code-block')).to.contain( - 'Example text 2' - ); - expect(await testSubjects.getVisibleText('ingestDataCodeExample-code-block')).to.contain( - 'Example text 3' - ); - }, - async clickFirstDocumentDeleteAction() { await testSubjects.existOrFail('documentMetadataButton'); await testSubjects.click('documentMetadataButton'); diff --git a/x-pack/test/functional/page_objects/snapshot_restore_page.ts b/x-pack/test/functional/page_objects/snapshot_restore_page.ts index 8c41f4a15c7f2..7a27081113212 100644 --- a/x-pack/test/functional/page_objects/snapshot_restore_page.ts +++ b/x-pack/test/functional/page_objects/snapshot_restore_page.ts @@ -10,6 +10,7 @@ import { FtrProviderContext } from '../ftr_provider_context'; export function SnapshotRestorePageProvider({ getService }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const retry = getService('retry'); + const find = getService('find'); return { async appTitleText() { @@ -44,28 +45,43 @@ export function SnapshotRestorePageProvider({ getService }: FtrProviderContext) 'Wait for register repository button to be on page', 10000, async () => { - return await testSubjects.isDisplayed('noRestoredSnapshotsHeader'); + return await testSubjects.isDisplayed( + emptyList ? 'noRestoredSnapshotsHeader' : 'restoreList' + ); } ); }, async navToSnapshots(emptyList: boolean = true) { await testSubjects.click('snapshots_tab'); await retry.waitForWithTimeout('Wait for snapshot list to be on page', 10000, async () => { - return await testSubjects.isDisplayed(emptyList ? 'snapshotListEmpty' : 'snapshotList'); + return await testSubjects.isDisplayed(emptyList ? 'emptyPrompt' : 'snapshotList'); }); }, - async fillCreateNewPolicyPageOne(policyName: string, snapshotName: string) { + async fillCreateNewPolicyPageOne( + policyName: string, + snapshotName: string, + repositoryName?: string + ) { await testSubjects.click('createPolicyButton'); await testSubjects.setValue('nameInput', policyName); await testSubjects.setValue('snapshotNameInput', snapshotName); + if (repositoryName) { + await testSubjects.selectValue('repositorySelect', repositoryName); + } await testSubjects.click('nextButton'); await retry.waitFor('all indices to be visible', async () => { return await testSubjects.isDisplayed('allIndicesToggle'); }); }, - async fillCreateNewPolicyPageTwo() { + async fillCreateNewPolicyPageTwo(singleIndexToSelect?: string) { + if (singleIndexToSelect) { + await testSubjects.click('allIndicesToggle'); + await testSubjects.click('useIndexPatternsButton'); + await testSubjects.setValue('comboBoxSearchInput', singleIndexToSelect); + await testSubjects.pressEnter('comboBoxSearchInput'); + } await testSubjects.click('nextButton'); await retry.waitFor('expire after value input to be visible', async () => { return await testSubjects.isDisplayed('expireAfterValueInput'); @@ -92,6 +108,18 @@ export function SnapshotRestorePageProvider({ getService }: FtrProviderContext) return await testSubjects.isDisplayed('policyLink'); }); }, + async closeSnaphsotFlyout() { + await testSubjects.click('euiFlyoutCloseButton'); + await retry.waitFor('snapshot table to be visible', async () => { + return await testSubjects.isDisplayed('snapshotLink'); + }); + }, + async closeRepositoriesFlyout() { + await testSubjects.click('srRepositoryDetailsFlyoutCloseButton'); + await retry.waitFor('repositories table to be visible', async () => { + return await testSubjects.isDisplayed('repositoryLink'); + }); + }, async getSnapshotList() { const table = await testSubjects.find('snapshotTable'); const rows = await table.findAllByTestSubject('row'); @@ -120,6 +148,18 @@ export function SnapshotRestorePageProvider({ getService }: FtrProviderContext) }) ); }, + async getRestoreStatusList() { + const table = await testSubjects.find('restoreList'); + const rows = await table.findAllByTestSubject('row'); + return await Promise.all( + rows.map(async (row) => { + return { + index: await row.findByTestSubject('restoreTableIndex'), + isComplete: await row.findByTestSubject('restoreTableIsComplete'), + }; + }) + ); + }, async viewRepositoryDetails(name: string) { const repos = await this.getRepoList(); if (repos.length === 1) { @@ -137,5 +177,100 @@ export function SnapshotRestorePageProvider({ getService }: FtrProviderContext) }); return await testSubjects.getVisibleText('cleanupCodeBlock'); }, + + async clickPolicyNameLink(name: string): Promise { + await find.clickByLinkText(name); + }, + + async clickRestoredStatusNameLink(name: string): Promise { + await find.clickByLinkText(name); + }, + + async clickPolicyActionButton() { + await testSubjects.click('policyActionMenuButton'); + await retry.waitFor('run button to be visible', async () => { + return await testSubjects.isDisplayed('policyActionMenuRunPolicy'); + }); + }, + + async clickRunPolicy() { + await testSubjects.click('policyActionMenuRunPolicy'); + await retry.waitFor('confirm modal to be visible', async () => { + return await testSubjects.isDisplayed('confirmModalConfirmButton'); + }); + }, + + async clickConfirmationModal() { + await testSubjects.click('confirmModalConfirmButton'); + }, + + async clickShowCollapsedIndicesIfPresent() { + if (await testSubjects.exists('collapsibleIndicesArrow')) { + await testSubjects.click('collapsibleIndicesArrow'); + } + }, + + async restoreSnapshot(indexName: string, rename: boolean = false) { + await testSubjects.click('restoreSnapshotButton'); + await retry.waitFor('restore form to be visible', async () => { + return await testSubjects.isDisplayed('snapshotRestoreApp'); + }); + + await testSubjects.click('allDsAndIndicesToggle'); + await testSubjects.click('restoreIndexPatternsButton'); + await testSubjects.setValue('comboBoxSearchInput', indexName); + await testSubjects.pressEnter('comboBoxSearchInput'); + + if (rename) { + await testSubjects.click('restoreRenameToggle'); + await testSubjects.setValue('capturePattern', `${indexName}(.*)`); + await testSubjects.setValue('replacementPattern', `restored_${indexName}$1`); + } + await testSubjects.click('nextButton'); + await retry.waitFor('index settings to be visible', async () => { + return await testSubjects.isDisplayed('indexSettingsTitle'); + }); + await testSubjects.click('nextButton'); + await retry.waitFor('review step to be visible', async () => { + return await testSubjects.isDisplayed('reviewSnapshotTitle'); + }); + await testSubjects.click('restoreButton'); + }, + + async createSourceOnlyRepositoryStepOne(repositoryName: string) { + await testSubjects.click('registerRepositoryButton'); + await testSubjects.setValue('nameInput', `${repositoryName}`); + await testSubjects.click('fsRepositoryType'); + await testSubjects.click('sourceOnlyToggle'); + await testSubjects.click('nextButton'); + await retry.waitFor('step two to be visible', async () => { + return await testSubjects.isDisplayed('stepTwo'); + }); + }, + async createSourceOnlyRepositoryStepTwo(location: string) { + await testSubjects.setValue('locationInput', location); + await testSubjects.click('compressToggle'); + await testSubjects.click('submitButton'); + await retry.waitFor('repository list to be visible', async () => { + return await testSubjects.isDisplayed('repositoryList'); + }); + }, + + async refreshWhileSnapshotIsInProgress() { + let isInProgress = true; + while (isInProgress) { + const table = await testSubjects.find('snapshotTable'); + const rows = await table.findAllByTestSubject('row'); + const snapshotState = await ( + await rows[0].findByTestSubject('snapshotState') + ).getVisibleText(); + + if (snapshotState === 'In progress') { + await testSubjects.click('reloadButton'); + } else { + isInProgress = false; + } + } + }, }; } diff --git a/x-pack/test/functional/services/ml/memory_usage.ts b/x-pack/test/functional/services/ml/memory_usage.ts index dadb1d10b2b83..64c9483c4f488 100644 --- a/x-pack/test/functional/services/ml/memory_usage.ts +++ b/x-pack/test/functional/services/ml/memory_usage.ts @@ -106,5 +106,13 @@ export function MachineLearningMemoryUsageProvider({ getService }: FtrProviderCo async assertEmptyTreeChartExists() { await testSubjects.existOrFail('mlJobTreeMap empty'); }, + + async assertJobTreeComboBoxExists() { + await testSubjects.existOrFail('mlJobTreeMapComboBox'); + }, + + async getJobTreeComboBoxOptions() { + return await comboBox.getOptions('mlJobTreeMapComboBox'); + }, }; } diff --git a/x-pack/test/functional/services/ml/notifications.ts b/x-pack/test/functional/services/ml/notifications.ts index 2365717d7226b..fb8d803cbb57f 100644 --- a/x-pack/test/functional/services/ml/notifications.ts +++ b/x-pack/test/functional/services/ml/notifications.ts @@ -16,6 +16,7 @@ export function NotificationsProvider( tableService: MlTableService ) { const testSubjects = getService('testSubjects'); + const find = getService('find'); return { async assertNotificationIndicatorExist(expectExist = true) { @@ -31,6 +32,21 @@ export function NotificationsProvider( expect(actualCount).to.greaterThan(expectedCount); }, + // This is a workaround for receiving available filter dropdown options, + // since EUI doesn't allow testSubjects for filters. + async getAvailableTypeFilters() { + const filterButton = await find.byCssSelector( + '.euiFilterGroup > *:nth-child(2) .euiFilterButton' + ); + await filterButton.click(); + const optionElements = await find.allByCssSelector('li[role="option"].euiSelectableListItem'); + const optionTexts = await Promise.all( + optionElements.map(async (element) => await element.getVisibleText()) + ); + + return optionTexts; + }, + table: tableService.getServiceInstance( 'NotificationsTable', 'mlNotificationsTable', diff --git a/x-pack/test/functional_search/tests/search_index_details.ts b/x-pack/test/functional_search/tests/search_index_details.ts index fccac0d31a145..65cd8b5ffac24 100644 --- a/x-pack/test/functional_search/tests/search_index_details.ts +++ b/x-pack/test/functional_search/tests/search_index_details.ts @@ -88,17 +88,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('should have basic example texts', async () => { await pageObjects.searchIndexDetailsPage.expectHasSampleDocuments(); }); - - it('should have other example texts when mapping changed', async () => { - await es.indices.putMapping({ - index: indexNameCodeExample, - properties: { - text: { type: 'text' }, - number: { type: 'integer' }, - }, - }); - await pageObjects.searchIndexDetailsPage.expectSampleDocumentsWithCustomMappings(); - }); }); describe('API key details', () => { diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/group1/view_case.ts b/x-pack/test/functional_with_es_ssl/apps/cases/group1/view_case.ts index 66c6a283714b8..2cc76239d369a 100644 --- a/x-pack/test/functional_with_es_ssl/apps/cases/group1/view_case.ts +++ b/x-pack/test/functional_with_es_ssl/apps/cases/group1/view_case.ts @@ -41,7 +41,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { // https://github.com/elastic/kibana/pull/190690 // fails after missing `awaits` were added - describe.skip('View case', () => { + describe('View case', () => { describe('page', () => { createOneCaseBeforeDeleteAllAfter(getPageObject, getService); @@ -581,12 +581,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { expect(await commentArea.getVisibleText()).to.be('Test comment from automation'); }); - /** - * There is this bug https://github.com/elastic/kibana/issues/157280 - * where this test randomly reproduces thus making the test flaky. - * Skipping for now until we fix it. - */ - it.skip('should persist the draft of new comment while description is updated', async () => { + it('should persist the draft of new comment while description is updated', async () => { let commentArea = await find.byCssSelector( '[data-test-subj="add-comment"] textarea.euiMarkdownEditorTextArea' ); @@ -787,6 +782,8 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { await cases.common.selectSeverity(CaseSeverity.MEDIUM); + await header.waitUntilLoadingHasFinished(); + await cases.common.changeCaseStatusViaDropdownAndVerify(CaseStatuses['in-progress']); await header.waitUntilLoadingHasFinished(); @@ -1277,7 +1274,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { await header.waitUntilLoadingHasFinished(); }); - afterEach(async () => { + after(async () => { await cases.api.deleteAllCases(); }); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/maintenance_windows/maintenance_windows_table.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/maintenance_windows/maintenance_windows_table.ts index 31aa069ba74c9..cce590d455c29 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/maintenance_windows/maintenance_windows_table.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/maintenance_windows/maintenance_windows_table.ts @@ -21,6 +21,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const browser = getService('browser'); // FLAKY: https://github.com/elastic/kibana/issues/205269 + // Failing: See https://github.com/elastic/kibana/issues/205269 describe.skip('Maintenance windows table', function () { beforeEach(async () => { await pageObjects.common.navigateToApp('maintenanceWindows'); diff --git a/x-pack/test/observability_ai_assistant_api_integration/common/create_llm_proxy.ts b/x-pack/test/observability_ai_assistant_api_integration/common/create_llm_proxy.ts index e18bf7e46c3fd..03b1dae289af3 100644 --- a/x-pack/test/observability_ai_assistant_api_integration/common/create_llm_proxy.ts +++ b/x-pack/test/observability_ai_assistant_api_integration/common/create_llm_proxy.ts @@ -37,7 +37,7 @@ export interface LlmResponseSimulator { content?: string; tool_calls?: Array<{ id: string; - index: string; + index: string | number; function?: { name: string; arguments: string; diff --git a/x-pack/test/observability_ai_assistant_api_integration/tests/knowledge_base/helpers.ts b/x-pack/test/observability_ai_assistant_api_integration/tests/knowledge_base/helpers.ts index f4b871679f8e8..2d7acb7fd485e 100644 --- a/x-pack/test/observability_ai_assistant_api_integration/tests/knowledge_base/helpers.ts +++ b/x-pack/test/observability_ai_assistant_api_integration/tests/knowledge_base/helpers.ts @@ -15,7 +15,7 @@ export const TINY_ELSER = { id: SUPPORTED_TRAINED_MODELS.TINY_ELSER.name, }; -export async function createKnowledgeBaseModel(ml: ReturnType) { +export async function importTinyElserModel(ml: ReturnType) { const config = { ...ml.api.getTrainedModelConfig(TINY_ELSER.name), input: { diff --git a/x-pack/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts b/x-pack/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts index d3208e5f1ff56..5ebd5f0d2324b 100644 --- a/x-pack/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts +++ b/x-pack/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts @@ -272,7 +272,19 @@ export default function ApiTest({ getService, getPageObjects }: FtrProviderConte conversationInterceptor.waitForIntercept(), ]); - await titleSimulator.next('My title'); + await titleSimulator.next({ + content: '', + tool_calls: [ + { + id: 'id', + index: 0, + function: { + name: 'title_conversation', + arguments: JSON.stringify({ title: 'My title' }), + }, + }, + ], + }); await titleSimulator.tokenCount({ completion: 1, prompt: 1, total: 2 }); diff --git a/x-pack/test/observability_ai_assistant_functional/tests/knowledge_base_management/index.spec.ts b/x-pack/test/observability_ai_assistant_functional/tests/knowledge_base_management/index.spec.ts index 300fec6aa45aa..87ada1e65a754 100644 --- a/x-pack/test/observability_ai_assistant_functional/tests/knowledge_base_management/index.spec.ts +++ b/x-pack/test/observability_ai_assistant_functional/tests/knowledge_base_management/index.spec.ts @@ -10,7 +10,7 @@ import { subj as testSubjSelector } from '@kbn/test-subj-selector'; import { TINY_ELSER, clearKnowledgeBase, - createKnowledgeBaseModel, + importTinyElserModel, deleteInferenceEndpoint, deleteKnowledgeBaseModel, } from '../../../observability_ai_assistant_api_integration/tests/knowledge_base/helpers'; @@ -53,7 +53,7 @@ export default function ApiTest({ getService, getPageObjects }: FtrProviderConte await clearKnowledgeBase(es); // create a knowledge base model - await createKnowledgeBaseModel(ml); + await importTinyElserModel(ml); await Promise.all([ // setup the knowledge base diff --git a/x-pack/test/plugin_api_integration/test_suites/task_manager/migrations.ts b/x-pack/test/plugin_api_integration/test_suites/task_manager/migrations.ts index b53da1b363bcb..61ac2377601df 100644 --- a/x-pack/test/plugin_api_integration/test_suites/task_manager/migrations.ts +++ b/x-pack/test/plugin_api_integration/test_suites/task_manager/migrations.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import type { TransportResult } from '@elastic/elasticsearch'; import { ConcreteTaskInstance, diff --git a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_management.ts b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_management.ts index 34ef9c2481bc1..508923815d762 100644 --- a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_management.ts +++ b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_management.ts @@ -8,7 +8,7 @@ import moment from 'moment'; import { random } from 'lodash'; import expect from '@kbn/expect'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { taskMappings as TaskManagerMapping } from '@kbn/task-manager-plugin/server/saved_objects/mappings'; import { ConcreteTaskInstance, BulkUpdateTaskResult } from '@kbn/task-manager-plugin/server'; import { FtrProviderContext } from '../../ftr_provider_context'; diff --git a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_partitions.ts b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_partitions.ts index 57e7fc107a7b4..fedfd259859e7 100644 --- a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_partitions.ts +++ b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_partitions.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { ConcreteTaskInstance } from '@kbn/task-manager-plugin/server'; import { taskMappings as TaskManagerMapping } from '@kbn/task-manager-plugin/server/saved_objects/mappings'; import { asyncForEach } from '@kbn/std'; diff --git a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_priority.ts b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_priority.ts index f8fc3f63987b9..3e20cec5fab93 100644 --- a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_priority.ts +++ b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_priority.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { ConcreteTaskInstance } from '@kbn/task-manager-plugin/server'; import { taskMappings as TaskManagerMapping } from '@kbn/task-manager-plugin/server/saved_objects/mappings'; import { asyncForEach } from '@kbn/std'; diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/ftr_config.ts b/x-pack/test/profiling_cypress/cli_config.ts similarity index 80% rename from x-pack/solutions/observability/plugins/profiling/e2e/ftr_config.ts rename to x-pack/test/profiling_cypress/cli_config.ts index 93af91f4792cb..c1341a04ad222 100644 --- a/x-pack/solutions/observability/plugins/profiling/e2e/ftr_config.ts +++ b/x-pack/test/profiling_cypress/cli_config.ts @@ -7,9 +7,8 @@ import type { FtrConfigProviderContext } from '@kbn/test'; import { CA_CERT_PATH } from '@kbn/dev-utils'; -import { commonFunctionalServices } from '@kbn/ftr-common-functional-services'; -import { commonFunctionalUIServices } from '@kbn/ftr-common-functional-ui-services'; import path from 'path'; +import { cypressTestRunner } from './runner'; const kibanaYamlFilePath = path.join(__dirname, './ftr_kibana.yml'); @@ -18,17 +17,12 @@ async function ftrConfig({ readConfigFile }: FtrConfigProviderContext) { require.resolve('@kbn/test-suites-src/common/config') ); const xpackFunctionalTestsConfig = await readConfigFile( - require.resolve('@kbn/test-suites-xpack/functional/config.base') + require.resolve('../functional/config.base.js') ); return { ...kibanaCommonTestsConfig.getAll(), - services: { - ...commonFunctionalServices, - ...commonFunctionalUIServices, - }, - esTestCluster: { ...xpackFunctionalTestsConfig.get('esTestCluster'), serverArgs: [ @@ -51,8 +45,8 @@ async function ftrConfig({ readConfigFile }: FtrConfigProviderContext) { `--config=${kibanaYamlFilePath}`, ], }, + testRunner: cypressTestRunner, }; } -// eslint-disable-next-line import/no-default-export export default ftrConfig; diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/es_archivers/profiling_data_anonymized.json b/x-pack/test/profiling_cypress/es_archivers/profiling_data_anonymized.json similarity index 100% rename from x-pack/solutions/observability/plugins/profiling/e2e/es_archivers/profiling_data_anonymized.json rename to x-pack/test/profiling_cypress/es_archivers/profiling_data_anonymized.json diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/ftr_kibana.yml b/x-pack/test/profiling_cypress/ftr_kibana.yml similarity index 100% rename from x-pack/solutions/observability/plugins/profiling/e2e/ftr_kibana.yml rename to x-pack/test/profiling_cypress/ftr_kibana.yml diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/load_profiling_data.ts b/x-pack/test/profiling_cypress/load_profiling_data.ts similarity index 100% rename from x-pack/solutions/observability/plugins/profiling/e2e/load_profiling_data.ts rename to x-pack/test/profiling_cypress/load_profiling_data.ts diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/cypress_test_runner.ts b/x-pack/test/profiling_cypress/runner.ts similarity index 58% rename from x-pack/solutions/observability/plugins/profiling/e2e/cypress_test_runner.ts rename to x-pack/test/profiling_cypress/runner.ts index d458f65df494f..bb8d1ad1af48a 100644 --- a/x-pack/solutions/observability/plugins/profiling/e2e/cypress_test_runner.ts +++ b/x-pack/test/profiling_cypress/runner.ts @@ -6,10 +6,8 @@ */ import axios from 'axios'; -import type cypress from 'cypress'; -import path from 'path'; import Url from 'url'; -import type { FtrProviderContext } from './ftr_provider_context'; +import type { FtrProviderContext } from '../common/ftr_provider_context'; import { loadProfilingData } from './load_profiling_data'; import { setupProfilingResources } from './setup_profiling_resources'; @@ -17,13 +15,8 @@ const DEFAULT_HEADERS = { 'kbn-xsrf': true, 'x-elastic-internal-origin': 'Kibana', }; -export async function cypressTestRunner({ - ftrProviderContext: { getService }, - cypressExecution, -}: { - ftrProviderContext: FtrProviderContext; - cypressExecution: typeof cypress.run | typeof cypress.open; -}) { + +export async function cypressTestRunner({ getService }: FtrProviderContext) { const config = getService('config'); const username = config.get('servers.elasticsearch.username'); @@ -53,12 +46,12 @@ export async function cypressTestRunner({ { headers: DEFAULT_HEADERS } ); - // Only runs the setup once. This is useful when runing the tests with --times args + // Only runs the setup once. This is useful when running the tests with --times args if (!profilingResources.data.has_setup) { await setupProfilingResources({ kibanaUrlWithAuth }); } - // Only loads profiling data once. This is useful when runing the tests with --times args + // Only loads profiling data once. This is useful when running the tests with --times args if (!profilingResources.data.has_data) { await loadProfilingData({ esNode, esRequestTimeout }); } @@ -69,42 +62,21 @@ export async function cypressTestRunner({ port: config.get('servers.kibana.port'), }); - const cypressProjectPath = path.join(__dirname); - const { open, ...cypressCliArgs } = getCypressCliArgs(); - - const res = await cypressExecution({ - ...cypressCliArgs, - project: cypressProjectPath, - config: { - e2e: { - baseUrl: kibanaUrlWithoutAuth, - }, - }, - env: { - KIBANA_URL: kibanaUrlWithoutAuth, - ES_NODE: esNode, - ES_REQUEST_TIMEOUT: esRequestTimeout, - TEST_CLOUD: process.env.TEST_CLOUD, - }, - }); - - return res; -} - -function getCypressCliArgs(): Record { - if (!process.env.CYPRESS_CLI_ARGS) { - return {}; - } - - const { $0, _, ...cypressCliArgs } = JSON.parse(process.env.CYPRESS_CLI_ARGS) as Record< - string, - unknown - >; - - const spec = - typeof cypressCliArgs.spec === 'string' && !cypressCliArgs.spec.includes('**') - ? `**/${cypressCliArgs.spec}*` - : cypressCliArgs.spec; - - return { ...cypressCliArgs, spec }; + return { + KIBANA_URL: kibanaUrlWithoutAuth, + ES_NODE: esNode, + ES_REQUEST_TIMEOUT: esRequestTimeout, + TEST_CLOUD: process.env.TEST_CLOUD, + baseUrl: Url.format({ + protocol: config.get('servers.kibana.protocol'), + hostname: config.get('servers.kibana.hostname'), + port: config.get('servers.kibana.port'), + }), + protocol: config.get('servers.kibana.protocol'), + hostname: config.get('servers.kibana.hostname'), + configport: config.get('servers.kibana.port'), + ELASTICSEARCH_URL: Url.format(config.get('servers.elasticsearch')), + ELASTICSEARCH_USERNAME: config.get('servers.kibana.username'), + ELASTICSEARCH_PASSWORD: config.get('servers.kibana.password'), + }; } diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/setup_profiling_resources.ts b/x-pack/test/profiling_cypress/setup_profiling_resources.ts similarity index 100% rename from x-pack/solutions/observability/plugins/profiling/e2e/setup_profiling_resources.ts rename to x-pack/test/profiling_cypress/setup_profiling_resources.ts diff --git a/x-pack/test/search_sessions_integration/config.ts b/x-pack/test/search_sessions_integration/config.ts index c3c0c3a42ddc9..bfb6700e43f9d 100644 --- a/x-pack/test/search_sessions_integration/config.ts +++ b/x-pack/test/search_sessions_integration/config.ts @@ -34,6 +34,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...xpackFunctionalConfig.get('kbnTestServer'), serverArgs: [ ...xpackFunctionalConfig.get('kbnTestServer.serverArgs'), + '--data.search.sessions.enabled=true', // enable search sessions '--data.search.sessions.management.refreshInterval=10s', // enable automatic refresh for sessions management screen ], }, diff --git a/x-pack/test/security_api_integration/tests/features/deprecated_features.ts b/x-pack/test/security_api_integration/tests/features/deprecated_features.ts index 35e502a58a343..acb50a8514a1a 100644 --- a/x-pack/test/security_api_integration/tests/features/deprecated_features.ts +++ b/x-pack/test/security_api_integration/tests/features/deprecated_features.ts @@ -183,6 +183,7 @@ export default function ({ getService }: FtrProviderContext) { "generalCases", "observabilityCases", "securitySolutionCases", + "siem", ] `); }); @@ -204,6 +205,7 @@ export default function ({ getService }: FtrProviderContext) { const featureIdsImplicitlyReplacedWithMultipleFeatures = new Set([ 'case_2_feature_a', 'case_4_feature_a', + 'siem', ]); for (const feature of features) { if ( diff --git a/x-pack/test/security_solution_api_integration/config/privileges/roles.ts b/x-pack/test/security_solution_api_integration/config/privileges/roles.ts new file mode 100644 index 0000000000000..54e32092d05ed --- /dev/null +++ b/x-pack/test/security_solution_api_integration/config/privileges/roles.ts @@ -0,0 +1,225 @@ +/* + * 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 { Role } from '../services/types'; + +/** + * Roles for privilege tests + */ + +export const secAllV1: Role = { + name: 'sec_all_v1', + privileges: { + elasticsearch: { + indices: [ + { + names: ['*'], + privileges: ['all'], + }, + ], + }, + kibana: [ + { + feature: { + siem: ['all'], + }, + spaces: ['*'], + }, + ], + }, +}; +export const secReadV1: Role = { + name: 'sec_read_v1', + privileges: { + elasticsearch: { + indices: [ + { + names: ['*'], + privileges: ['read'], + }, + ], + }, + kibana: [ + { + feature: { + siem: ['read'], + }, + spaces: ['*'], + }, + ], + }, +}; +export const secNoneV1: Role = { + name: 'sec_none_v1', + privileges: { + elasticsearch: { + indices: [ + { + names: ['*'], + privileges: ['read'], + }, + ], + }, + kibana: [ + { + feature: { + siem: ['none'], + }, + spaces: ['*'], + }, + ], + }, +}; + +export const secTimelineAllV2: Role = { + name: 'sec_timeline_all', + privileges: { + elasticsearch: { + indices: [ + { + names: ['*'], + privileges: ['all'], + }, + ], + }, + kibana: [ + { + feature: { + siemV2: ['all'], + securitySolutionTimeline: ['all'], + }, + spaces: ['*'], + }, + ], + }, +}; + +export const secTimelineReadV2: Role = { + name: 'sec_timeline_read', + privileges: { + elasticsearch: { + indices: [ + { + names: ['*'], + privileges: ['read'], + }, + ], + }, + kibana: [ + { + feature: { + siemV2: ['read'], + securitySolutionTimeline: ['read'], + }, + spaces: ['*'], + }, + ], + }, +}; + +export const secTimelineNoneV2: Role = { + name: 'sec_timeline_none', + privileges: { + elasticsearch: { + indices: [ + { + names: ['*'], + privileges: ['read'], + }, + ], + }, + kibana: [ + { + feature: { + siemV2: ['read'], + securitySolutionTimeline: ['none'], + }, + spaces: ['*'], + }, + ], + }, +}; + +export const secNotesAllV2: Role = { + name: 'sec_notes_all', + privileges: { + elasticsearch: { + indices: [ + { + names: ['*'], + privileges: ['all'], + }, + ], + }, + kibana: [ + { + feature: { + siemV2: ['all'], + securitySolutionNotes: ['all'], + }, + spaces: ['*'], + }, + ], + }, +}; + +export const secNotesReadV2: Role = { + name: 'sec_notes_read', + privileges: { + elasticsearch: { + indices: [ + { + names: ['*'], + privileges: ['read'], + }, + ], + }, + kibana: [ + { + feature: { + siemV2: ['read'], + securitySolutionNotes: ['read'], + }, + spaces: ['*'], + }, + ], + }, +}; + +export const secNotesNoneV2: Role = { + name: 'sec_notes_none', + privileges: { + elasticsearch: { + indices: [ + { + names: ['*'], + privileges: ['read'], + }, + ], + }, + kibana: [ + { + feature: { + siemV2: ['none'], + securitySolutionNotes: ['none'], + }, + spaces: ['*'], + }, + ], + }, +}; + +export const roles: Role[] = [ + secTimelineAllV2, + secTimelineReadV2, + secTimelineNoneV2, + secNotesAllV2, + secNotesReadV2, + secNotesNoneV2, + secAllV1, + secReadV1, + secNoneV1, +]; diff --git a/x-pack/test/security_solution_api_integration/config/privileges/users.ts b/x-pack/test/security_solution_api_integration/config/privileges/users.ts new file mode 100644 index 0000000000000..a107df1c43386 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/config/privileges/users.ts @@ -0,0 +1,89 @@ +/* + * 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 { User } from '../services/types'; +import { + secAllV1, + secNoneV1, + secReadV1, + secNotesAllV2, + secNotesReadV2, + secNotesNoneV2, + secTimelineAllV2, + secTimelineReadV2, + secTimelineNoneV2, +} from './roles'; + +/** + * Users for privilege tests + */ + +export const secAllV1User: User = { + username: 'sec_v1_all', + password: 'password', + roles: [secAllV1.name], +}; + +export const secReadV1User: User = { + username: 'sec_v1_read', + password: 'password', + roles: [secReadV1.name], +}; + +export const secNoneV1User: User = { + username: 'sec_v1_none', + password: 'password', + roles: [secNoneV1.name], +}; + +export const secNotesAllUser: User = { + username: 'sec_Notes_All', + password: 'password', + roles: [secNotesAllV2.name], +}; + +export const secNotesReadUser: User = { + username: 'sec_Notes_Read', + password: 'password', + roles: [secNotesReadV2.name], +}; + +export const secNotesNoneUser: User = { + username: 'sec_Notes_None', + password: 'password', + roles: [secNotesNoneV2.name], +}; + +export const secTimelineAllUser: User = { + username: 'sec_timeline_All', + password: 'password', + roles: [secTimelineAllV2.name], +}; + +export const secTimelineReadUser: User = { + username: 'sec_timeline_Read', + password: 'password', + roles: [secTimelineReadV2.name], +}; + +export const secTimelineNoneUser: User = { + username: 'sec_timeline_None', + password: 'password', + roles: [secTimelineNoneV2.name], +}; + +export const allUsers: User[] = [ + secAllV1User, + secReadV1User, + secNoneV1User, + secNotesAllUser, + secNotesNoneUser, + secNotesReadUser, + secTimelineAllUser, + secTimelineNoneUser, + secTimelineReadUser, +]; diff --git a/x-pack/test/security_solution_api_integration/config/services/security_solution_edr_workflows_roles_users.ts b/x-pack/test/security_solution_api_integration/config/services/security_solution_edr_workflows_roles_users.ts index 92e0cc9ba1f13..a61d9b24e1a41 100644 --- a/x-pack/test/security_solution_api_integration/config/services/security_solution_edr_workflows_roles_users.ts +++ b/x-pack/test/security_solution_api_integration/config/services/security_solution_edr_workflows_roles_users.ts @@ -53,8 +53,8 @@ export function RolesUsersProvider({ getService }: FtrProviderContext) { if (predefinedRole) { const roleConfig = rolesMapping[predefinedRole]; if (extraPrivileges) { - roleConfig.kibana[0].feature.siem = [ - ...roleConfig.kibana[0].feature.siem, + roleConfig.kibana[0].feature.siemV2 = [ + ...roleConfig.kibana[0].feature.siemV2, ...extraPrivileges, ]; } @@ -74,7 +74,7 @@ export function RolesUsersProvider({ getService }: FtrProviderContext) { spaces: ['*'], base: [], feature: { - siem: customRole.extraPrivileges, + siemV2: customRole.extraPrivileges, }, }, ], 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 index 971fe91ea8d74..ecc8b6747d04e 100644 --- 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 @@ -8,7 +8,7 @@ import { format as formatUrl } from 'url'; import supertest from 'supertest'; import { FtrProviderContextWithSpaces } from '../../ftr_provider_context_with_spaces'; -import { SecuritySolutionESSUtilsInterface } from './types'; +import { SecuritySolutionESSUtilsInterface, Role, User } from './types'; export function SecuritySolutionESSUtils({ getService, @@ -16,21 +16,63 @@ export function SecuritySolutionESSUtils({ const config = getService('config'); const search = getService('search'); const supertestWithoutAuth = getService('supertest'); + const security = getService('security'); + + const createSuperTest = async (role?: string, password: string = 'changeme') => { + if (!role) { + return supertestWithoutAuth; + } + const kbnUrl = formatUrl({ + ...config.get('servers.kibana'), + auth: false, + }); + + return supertest.agent(kbnUrl).auth(role, password); + }; return { getUsername: (_role?: string) => Promise.resolve(config.get('servers.kibana.username') as string), createSearch: (_role?: string) => Promise.resolve(search), - createSuperTest: async (role?: string, password: string = 'changeme') => { - if (!role) { - return supertestWithoutAuth; + + createSuperTest, + + createSuperTestWithUser: (user: User) => { + return createSuperTest(user.username, user.password); + }, + + cleanUpCustomRole: () => { + // In ESS this is a no-op + return Promise.resolve(); + }, + + async createUser(user: User): Promise { + const { username, roles, password } = user; + await security.user.create(username, { roles, password: password ?? 'changeme' }); + }, + + /** + * Deletes specified users by username + * @param names[] + */ + async deleteUsers(names: string[]): Promise { + for (const name of names) { + await security.user.delete(name); } - const kbnUrl = formatUrl({ - ...config.get('servers.kibana'), - auth: false, - }); + }, - return supertest.agent(kbnUrl).auth(role, password); + async createRole(name: string, role: Role) { + return await security.role.create(name, role.privileges); + }, + + /** + * Deletes specified roles by name + * @param roles[] + */ + async deleteRoles(roles: string[]): Promise { + for (const role of roles) { + await security.role.delete(role); + } }, }; } 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 index 1c41ba20bb6f7..6e7e0561e6b21 100644 --- 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 @@ -12,7 +12,8 @@ import { RoleCredentials } from '@kbn/test-suites-serverless/shared/services'; import type { SendOptions } from '@kbn/ftr-common-functional-services'; import type { SendOptions as SecureSearchSendOptions } from '@kbn/test-suites-serverless/shared/services/search_secure'; import type { FtrProviderContext } from '../../ftr_provider_context'; -import type { SecuritySolutionUtilsInterface } from './types'; +import type { SecuritySolutionUtilsInterface, User } from './types'; +import { roles } from '../privileges/roles'; export function SecuritySolutionServerlessUtils({ getService, @@ -71,6 +72,32 @@ export function SecuritySolutionServerlessUtils({ */ createSuperTest, + createSuperTestWithUser: async (user: User) => { + if (user.roles.length > 1) { + throw new Error( + `This test service only supports authentication for users with a single role. Error for ${ + user.username + } with roles ${user.roles.join(',')}.` + ); + } + const userRoleName = user.roles[0]; + const roleDefinition = roles.find((role) => role.name === userRoleName); + if (!roleDefinition) { + throw new Error(`Could not find a role definition for ${userRoleName}`); + } + await svlUserManager.setCustomRole(roleDefinition.privileges); + const roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('customRole'); + const superTest = supertest + .agent(kbnUrl) + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); + return superTest; + }, + + cleanUpCustomRole: async () => { + await svlUserManager.deleteCustomRole(); + }, + createSearch: async (role = 'admin') => { const apiKeyHeader = rolesCredentials.get(role)?.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 index d173ffb6181fb..2112b05c2e20f 100644 --- a/x-pack/test/security_solution_api_integration/config/services/types.ts +++ b/x-pack/test/security_solution_api_integration/config/services/types.ts @@ -18,11 +18,53 @@ export interface SecuritySolutionServerlessSearch extends Omit Promise; createSuperTest: (role?: string) => Promise>; + createSuperTestWithUser: (user: User) => Promise>; createSearch: (role?: string) => Promise; + cleanUpCustomRole: () => Promise; +} + +interface FeaturesPrivileges { + [featureId: string]: string[]; +} + +interface ElasticsearchIndices { + names: string[]; + privileges: string[]; +} + +export interface Role { + name: string; + privileges: { + elasticsearch: ElasticSearchPrivilege; + kibana: KibanaPrivilege[]; + }; +} +export interface ElasticSearchPrivilege { + cluster?: string[]; + indices?: ElasticsearchIndices[]; +} + +export interface KibanaPrivilege { + spaces: string[]; + base?: string[]; + feature?: FeaturesPrivileges; +} + +export interface User { + username: string; + password: string; + description?: string; + roles: string[]; } export interface SecuritySolutionESSUtilsInterface { getUsername: (role?: string) => Promise; createSearch: (role?: string) => Promise; createSuperTest: (role?: string, password?: string) => Promise>; + createSuperTestWithUser: (user: User) => Promise>; + cleanUpCustomRole: () => Promise; + createUser: (user: User) => Promise; + deleteUsers: (userNames: string[]) => Promise; + createRole: (name: string, role: Role) => Promise; + deleteRoles: (roleNames: string[]) => Promise; } diff --git a/x-pack/test/security_solution_api_integration/package.json b/x-pack/test/security_solution_api_integration/package.json index 2810ff5108a1b..eacae90d7f323 100644 --- a/x-pack/test/security_solution_api_integration/package.json +++ b/x-pack/test/security_solution_api_integration/package.json @@ -17,6 +17,12 @@ "initialize-server:ea:basic_essentials": "node ./scripts/index.js server entity_analytics basic_license_essentials_tier", "run-tests:ea:basic_essentials": "node ./scripts/index.js runner entity_analytics basic_license_essentials_tier", + "initialize-server:asset_inventory:trial_complete": "node ./scripts/index.js server asset_inventory trial_license_complete_tier", + "run-tests:asset_inventory:trial_complete": "node ./scripts/index.js runner asset_inventory trial_license_complete_tier", + + "asset_inventory:entity_store:server:ess": "npm run initialize-server:asset_inventory:trial_complete entity_store ess", + "asset_inventory:entity_store:runner:ess": "npm run run-tests:asset_inventory:trial_complete entity_store ess essEnv --", + "initialize-server:dr": "node ./scripts/index.js server detections_response trial_license_complete_tier", "run-tests:dr": "node ./scripts/index.js runner detections_response trial_license_complete_tier", diff --git a/x-pack/test/security_solution_api_integration/test_suites/asset_inventory/entity_store/trial_license_complete_tier/configs/ess.config.ts b/x-pack/test/security_solution_api_integration/test_suites/asset_inventory/entity_store/trial_license_complete_tier/configs/ess.config.ts new file mode 100644 index 0000000000000..03814bdd3daba --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/asset_inventory/entity_store/trial_license_complete_tier/configs/ess.config.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 { FtrConfigProviderContext } from '@kbn/test'; +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile( + require.resolve('../../../../../config/ess/config.base.trial') + ); + + return { + ...functionalConfig.getAll(), + kbnTestServer: { + ...functionalConfig.get('kbnTestServer'), + serverArgs: [ + ...functionalConfig.get('kbnTestServer.serverArgs'), + `--xpack.securitySolution.enableExperimental=${JSON.stringify([])}`, + ], + }, + testFiles: [require.resolve('..')], + junit: { + reportName: 'Asset Inventory Integration Tests - ESS Env - Basic License', + }, + }; +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/asset_inventory/entity_store/trial_license_complete_tier/index.ts b/x-pack/test/security_solution_api_integration/test_suites/asset_inventory/entity_store/trial_license_complete_tier/index.ts new file mode 100644 index 0000000000000..715fa42083f35 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/asset_inventory/entity_store/trial_license_complete_tier/index.ts @@ -0,0 +1,14 @@ +/* + * 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'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('Asset Inventory - Entity Store', function () { + loadTestFile(require.resolve('./keyword_builder_ingest_pipeline')); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/asset_inventory/entity_store/trial_license_complete_tier/keyword_builder_ingest_pipeline.ts b/x-pack/test/security_solution_api_integration/test_suites/asset_inventory/entity_store/trial_license_complete_tier/keyword_builder_ingest_pipeline.ts new file mode 100644 index 0000000000000..67b2238176a3a --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/asset_inventory/entity_store/trial_license_complete_tier/keyword_builder_ingest_pipeline.ts @@ -0,0 +1,64 @@ +/* + * 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 expect from '@kbn/expect'; + +import { buildIngestPipeline } from '@kbn/security-solution-plugin/server/lib/asset_inventory/ingest_pipelines'; +import { applyIngestProcessorToDoc } from '../utils/ingest'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default ({ getService }: FtrProviderContext) => { + const es = getService('es'); + const log = getService('log'); + + const applyOperatorToDoc = async (docSource: any): Promise => { + const steps = buildIngestPipeline(); + + return applyIngestProcessorToDoc(steps, docSource, es, log); + }; + + describe('@ess @skipInServerlessMKI Asset Inventory - Entity store - Keyword builder pipeline', () => { + it('should build entities.keyword when entities.metadata is provided ', async () => { + const doc = { + related: { + entity: ['entity-id-1', 'entity-id-2', 'entity-id-3'], + }, + entities: { + metadata: { + 'entity-id-1': { + entity: { + type: 'SomeType', + }, + cloud: { + region: 'us-east-1', + }, + someECSfield: 'someECSfieldValue', + SomeNonECSField: 'SomeNonECSValue', + }, + 'entity-id-2': { + entity: { + type: 'SomeOtherType', + }, + SomeNonECSField: 'SomeNonECSValue', + }, + 'entity-id-3': { + someECSfield: 'someECSfieldValue', + }, + }, + }, + }; + + const resultDoc = await applyOperatorToDoc(doc); + + expect(resultDoc.entities.keyword).to.eql([ + '{"entity-id-3":{"someECSfield":"someECSfieldValue"}}', + '{"entity-id-2":{"SomeNonECSField":"SomeNonECSValue","entity":{"type":"SomeOtherType"}}}', + '{"entity-id-1":{"cloud":{"region":"us-east-1"},"SomeNonECSField":"SomeNonECSValue","someECSfield":"someECSfieldValue","entity":{"type":"SomeType"}}}', + ]); + }); + }); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/asset_inventory/entity_store/utils/ingest.ts b/x-pack/test/security_solution_api_integration/test_suites/asset_inventory/entity_store/utils/ingest.ts new file mode 100644 index 0000000000000..aec5812332ab2 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/asset_inventory/entity_store/utils/ingest.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Client } from '@elastic/elasticsearch'; +import { IngestProcessorContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { ToolingLog } from '@kbn/tooling-log'; + +export const applyIngestProcessorToDoc = async ( + steps: IngestProcessorContainer[], + docSource: any, + es: Client, + log: ToolingLog +): Promise => { + const doc = { + _index: 'index', + _id: 'id', + _source: docSource, + }; + + const res = await es.ingest.simulate({ + pipeline: { + description: 'test', + processors: steps, + }, + docs: [doc], + }); + + const firstDoc = res.docs?.[0]; + + const error = firstDoc?.error; + if (error) { + log.error('Full painless error below: '); + log.error(JSON.stringify(error, null, 2)); + throw new Error('Painless error running pipeline see logs for full detail : ' + error?.type); + } + + return firstDoc?.doc?._source; +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/actions/trial_license_complete_tier/check_privileges.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/actions/trial_license_complete_tier/check_privileges.ts index c45bf13c66aad..251fc7c74d71f 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/actions/trial_license_complete_tier/check_privileges.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/actions/trial_license_complete_tier/check_privileges.ts @@ -52,15 +52,16 @@ export default ({ getService }: FtrProviderContext) => { await deleteAllRules(supertest, log); }); - describe('should set status to partial failure when user has no access', () => { + context('when all indices exist but user cannot read host_alias', () => { const indexTestCases = [ ['host_alias'], ['host_alias', 'auditbeat-8.0.0'], ['host_alias*'], ['host_alias*', 'auditbeat-*'], ]; + indexTestCases.forEach((index) => { - it(`for KQL rule with index param: ${index}`, async () => { + it(`sets rule status to partial failure for KQL rule with index param: ${index}`, async () => { const rule = { ...getRuleForAlertTesting(index), query: 'process.executable: "/usr/bin/sudo"', @@ -90,13 +91,55 @@ export default ({ getService }: FtrProviderContext) => { await deleteUserAndRole(getService, ROLES.detections_admin); }); }); + }); + + context('when some specified indices do not exist, but user can read all others', () => {}); + + describe('when no specified indices exist', () => { + describe('for a query rule', () => { + it('sets rule status to partial failure and does not execute', async () => { + const rule = getRuleForAlertTesting(['non-existent-index']); + await createUserAndRole(getService, ROLES.detections_admin); + const { id } = await createRuleWithAuth(supertestWithoutAuth, rule, { + user: ROLES.detections_admin, + pass: 'changeme', + }); + + await waitForRulePartialFailure({ + supertest, + log, + id, + }); + const { body } = await supertest + .get(DETECTION_ENGINE_RULES_URL) + .set('kbn-xsrf', 'true') + .set('elastic-api-version', '2023-10-31') + .query({ id }) + .expect(200); + + // TODO: https://github.com/elastic/kibana/pull/121644 clean up, make type-safe + const lastExecution = body?.execution_summary?.last_execution; + + expect(lastExecution.message).to.contain( + 'This rule is attempting to query data from Elasticsearch indices listed in the "Index patterns" section of the rule definition, however no index matching: ["non-existent-index"] was found. This warning will continue to appear until a matching index is created or this rule is disabled.' + ); + + // no metrics == no work performed, presumably + expect(lastExecution.metrics).to.eql({}); + + await deleteUserAndRole(getService, ROLES.detections_admin); + }); + }); + }); + context('for threshold rules', () => { const thresholdIndexTestCases = [ ['host_alias', 'auditbeat-8.0.0'], ['host_alias*', 'auditbeat-*'], ]; + thresholdIndexTestCases.forEach((index) => { - it(`for threshold rule with index param: ${index}`, async () => { + it(`with index param: ${index}`, async () => { const rule: ThresholdRuleCreateProps = { ...getThresholdRuleForAlertTesting(index), threshold: { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/trial_license_complete_tier/document_level_security.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/trial_license_complete_tier/document_level_security.ts index 2c8c0c2a599c4..af35ceba994e5 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/trial_license_complete_tier/document_level_security.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/trial_license_complete_tier/document_level_security.ts @@ -24,7 +24,7 @@ const roleToAccessSecuritySolution = { kibana: [ { feature: { - siem: ['all'], + siemV2: ['all'], }, spaces: ['*'], }, @@ -47,7 +47,7 @@ const roleToAccessSecuritySolutionWithDls = { kibana: [ { feature: { - siem: ['all'], + siemV2: ['all'], }, spaces: ['*'], }, 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 10bde240ec36c..c09be3fe35016 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 @@ -162,7 +162,7 @@ export default ({ getService }: FtrProviderContext) => { const rule = await fetchRule(supertest, { id }); expect(rule?.execution_summary?.last_execution.status).toBe('partial failure'); - expect(rule?.execution_summary?.last_execution.message).toBe( + expect(rule?.execution_summary?.last_execution.message).toContain( 'This rule is attempting to query data from Elasticsearch indices listed in the "Index patterns" section of the rule definition, however no index matching: ["does-not-exist-*"] was found. This warning will continue to appear until a matching index is created or this rule is disabled.' ); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/entity_store/trial_license_complete_tier/asset_inventory_pipeline.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/entity_store/trial_license_complete_tier/asset_inventory_pipeline.ts new file mode 100644 index 0000000000000..ca8d7b15cb81e --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/entity_store/trial_license_complete_tier/asset_inventory_pipeline.ts @@ -0,0 +1,157 @@ +/* + * 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 expect from '@kbn/expect'; +import { entityMetadataExtractorProcessor } from '@kbn/security-solution-plugin/server/lib/entity_analytics/entity_store/entity_definitions/entity_descriptions/universal'; +import { dynamicNewestRetentionSteps } from '@kbn/security-solution-plugin/server/lib/entity_analytics/entity_store/field_retention/dynamic_retention'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; +import { applyIngestProcessorToDoc } from '../utils/ingest'; + +export default ({ getService }: FtrProviderContext) => { + const es = getService('es'); + const log = getService('log'); + describe('@ess @serverless @skipInServerlessMKI Asset Inventory - universal entity engine pipeline ', () => { + describe('Entity metadata extractor processor step', () => { + it('should extract metadata from "collected.metadata" and add it to the document', async () => { + const metadata = { + test: { + cloud: { super: 123 }, + okta: { foo: { baz: { qux: 1 } } }, + }, + }; + const doc = { + collected: { + metadata: [JSON.stringify(metadata)], + }, + entity: { + id: 'test', + }, + }; + + const result = await applyIngestProcessorToDoc( + [entityMetadataExtractorProcessor], + doc, + es, + log + ); + + const processed = { + ...doc, + ...metadata.test, + }; + + return expect(result).to.eql(processed); + }); + }); + + describe('prefer newest value for dynamic entities', () => { + it('should return latest value if no history value', async () => { + const metadata = { + cloud: { super: 123 }, + }; + + const doc = metadata; + + const processor = dynamicNewestRetentionSteps([]); + const result = await applyIngestProcessorToDoc([processor], doc, es, log); + + return expect(result).to.eql(doc); + }); + + it('should return history value if no latest value is found', async () => { + const metadata = { + cloud: { super: 123 }, + }; + + const doc = { + historical: metadata, + }; + + const processor = dynamicNewestRetentionSteps([]); + const result = await applyIngestProcessorToDoc([processor], doc, es, log); + + return expect(result).to.eql({ + ...doc, + ...metadata, + }); + }); + + it('should return latest value if both historical and latest values exist', async () => { + const metadata = { + cloud: { super: 123 }, + }; + + const historical = { + cloud: { super: 456 }, + }; + + const doc = { + historical, + ...metadata, + }; + + const processor = dynamicNewestRetentionSteps([]); + const result = await applyIngestProcessorToDoc([processor], doc, es, log); + + return expect(result).to.eql(doc); + }); + + it('should merge nested object preserving historical values not found in latest', async () => { + const metadata = { + cloud: { host: 'test' }, + okta: { foo: { bar: { baz: 1 } } }, + }; + + const historical = { + cloud: { user: 'agent' }, + okta: { foo: { bar: { qux: 11 } } }, + }; + + const doc = { + historical, + ...metadata, + }; + + const processor = dynamicNewestRetentionSteps([]); + const result = await applyIngestProcessorToDoc([processor], doc, es, log); + + return expect(result).to.eql({ + historical, + cloud: { host: 'test', user: 'agent' }, + okta: { foo: { bar: { baz: 1, qux: 11 } } }, + }); + }); + + it('should ignore historical static fields', async () => { + const metadata = { + cloud: { host: 'test' }, + }; + + const historical = { + static: 'static', + cloud: { user: 'agent' }, + okta: { foo: { bar: { qux: 1 } } }, + }; + + const doc = { + historical, + ...metadata, + }; + + const staticFields = ['static']; + const processor = dynamicNewestRetentionSteps(staticFields); + const result = await applyIngestProcessorToDoc([processor], doc, es, log); + + return expect(result).to.eql({ + historical, + cloud: { host: 'test', user: 'agent' }, + okta: { foo: { bar: { qux: 1 } } }, + }); + }); + }); + }); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/entity_store/trial_license_complete_tier/index.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/entity_store/trial_license_complete_tier/index.ts index 899dbc68102f3..a6fb4cf805f2d 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/entity_store/trial_license_complete_tier/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/entity_store/trial_license_complete_tier/index.ts @@ -13,5 +13,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./entity_store')); loadTestFile(require.resolve('./field_retention_operators')); loadTestFile(require.resolve('./entity_store_nondefault_spaces')); + loadTestFile(require.resolve('./asset_inventory_pipeline')); }); } diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/entity_store/utils/ingest.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/entity_store/utils/ingest.ts index aec5812332ab2..e934281fcea3b 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/entity_store/utils/ingest.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/entity_store/utils/ingest.ts @@ -20,23 +20,26 @@ export const applyIngestProcessorToDoc = async ( _id: 'id', _source: docSource, }; + try { + const res = await es.ingest.simulate({ + pipeline: { + description: 'test', + processors: steps, + }, + docs: [doc], + }); - const res = await es.ingest.simulate({ - pipeline: { - description: 'test', - processors: steps, - }, - docs: [doc], - }); + const firstDoc = res.docs?.[0]; - const firstDoc = res.docs?.[0]; - - const error = firstDoc?.error; - if (error) { - log.error('Full painless error below: '); - log.error(JSON.stringify(error, null, 2)); - throw new Error('Painless error running pipeline see logs for full detail : ' + error?.type); + const error = firstDoc?.error; + if (error) { + log.error('Full painless error below: '); + log.error(JSON.stringify(error, null, 2)); + throw new Error('Painless error running pipeline see logs for full detail : ' + error?.type); + } + return firstDoc?.doc?._source; + } catch (e) { + log.error('Error running pipeline'); + throw e; } - - return firstDoc?.doc?._source; }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/asset_criticality.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/asset_criticality.ts index d5d802acb3922..71f7642982f38 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/asset_criticality.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/asset_criticality.ts @@ -71,7 +71,7 @@ export default ({ getService }: FtrProviderContext) => { assetCriticalityIndexResult['.asset-criticality.asset-criticality-default']?.mappings ).to.eql({ _meta: { - version: 2, + version: 3, }, dynamic: 'strict', properties: { @@ -81,6 +81,13 @@ export default ({ getService }: FtrProviderContext) => { criticality_level: { type: 'keyword', }, + event: { + properties: { + ingested: { + type: 'date', + }, + }, + }, id_field: { type: 'keyword', }, @@ -160,8 +167,7 @@ export default ({ getService }: FtrProviderContext) => { expect(result['@timestamp']).to.be.a('string'); const doc = await getAssetCriticalityDoc({ idField: 'host.name', idValue: 'host-01', es }); - - expect(doc).to.eql(result); + expect(_.omit(doc, 'event')).to.eql(result); }); it('should return 400 if criticality is invalid', async () => { @@ -372,7 +378,7 @@ export default ({ getService }: FtrProviderContext) => { const doc = await getAssetCriticalityDoc({ idField: 'host.name', idValue: 'host-01', es }); - expect(doc).to.eql(updatedDoc); + expect(_.omit(doc, 'event')).to.eql(_.omit(updatedDoc, 'event')); }); }); @@ -387,7 +393,7 @@ export default ({ getService }: FtrProviderContext) => { idValue: expectedDoc.id_value, }); - expect(omit(esDoc, '@timestamp')).to.eql(expectedDoc); + expect(omit(esDoc, ['@timestamp', 'event'])).to.eql(expectedDoc); }; it('should return 400 if the records array is empty', async () => { @@ -478,9 +484,8 @@ export default ({ getService }: FtrProviderContext) => { await assetCriticalityRoutes.upsert(assetCriticality); const res = await assetCriticalityRoutes.delete('host.name', 'delete-me'); - expect(res.body.deleted).to.eql(true); - expect(_.omit(res.body.record, '@timestamp')).to.eql( + expect(_.omit(res.body.record, ['@timestamp', 'event'])).to.eql( assetCreateTypeToAssetRecord(assetCriticality) ); @@ -494,7 +499,9 @@ export default ({ getService }: FtrProviderContext) => { ...assetCriticality, criticality_level: CRITICALITY_VALUES.DELETED, }; - expect(_.omit(doc, '@timestamp')).to.eql(assetCreateTypeToAssetRecord(deletedDoc)); + expect(_.omit(doc, ['@timestamp', 'event'])).to.eql( + assetCreateTypeToAssetRecord(deletedDoc) + ); }); it('should not return 404 if the asset criticality does not exist', async () => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/asset_criticality_privileges.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/asset_criticality_privileges.ts index bd22e51a6a551..24c5349691e4d 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/asset_criticality_privileges.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/asset_criticality_privileges.ts @@ -18,7 +18,7 @@ const ROLES = [ kibana: [ { feature: { - siem: ['read'], + siemV2: ['read'], }, spaces: ['default'], }, diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/init_and_status_apis.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/init_and_status_apis.ts index f87916d1af12b..3252621024dc0 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/init_and_status_apis.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/init_and_status_apis.ts @@ -71,6 +71,8 @@ export default ({ getService }: FtrProviderContext) => { const dataStreamName = 'risk-score.risk-score-default'; const latestIndexName = 'risk-score.risk-score-latest-default'; const transformId = 'risk_score_latest_transform_default'; + const defaultPipeline = + 'entity_analytics_create_eventIngest_from_timestamp-pipeline-default'; await riskEngineRoutes.init(); @@ -89,6 +91,13 @@ export default ({ getService }: FtrProviderContext) => { ignore_malformed: false, type: 'date', }, + event: { + properties: { + ingested: { + type: 'date', + }, + }, + }, host: { properties: { name: { @@ -288,6 +297,7 @@ export default ({ getService }: FtrProviderContext) => { expect(indexTemplate.index_template.template!.settings).to.eql({ index: { + default_pipeline: defaultPipeline, mapping: { total_fields: { limit: '1000', @@ -341,6 +351,7 @@ export default ({ getService }: FtrProviderContext) => { const dataStreamName = `risk-score.risk-score-${customSpaceName}`; const latestIndexName = `risk-score.risk-score-latest-${customSpaceName}`; const transformId = `risk_score_latest_transform_${customSpaceName}`; + const defaultPipeline = `entity_analytics_create_eventIngest_from_timestamp-pipeline-${customSpaceName}`; await riskEngineRoutesWithNamespace.init(); @@ -359,6 +370,13 @@ export default ({ getService }: FtrProviderContext) => { ignore_malformed: false, type: 'date', }, + event: { + properties: { + ingested: { + type: 'date', + }, + }, + }, host: { properties: { name: { @@ -562,6 +580,7 @@ export default ({ getService }: FtrProviderContext) => { expect(indexTemplate.index_template.template!.settings).to.eql({ index: { + default_pipeline: defaultPipeline, mapping: { total_fields: { limit: '1000', @@ -626,7 +645,7 @@ export default ({ getService }: FtrProviderContext) => { start: 'now-30d', }, _meta: { - mappingsVersion: 2, + mappingsVersion: 3, }, }); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/risk_engine_privileges.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/risk_engine_privileges.ts index 6b4639030e785..93b9573d3e3aa 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/risk_engine_privileges.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/risk_engine_privileges.ts @@ -16,7 +16,7 @@ const ROLES = [ kibana: [ { feature: { - siem: ['read'], + siemV2: ['read'], }, spaces: ['default'], }, diff --git a/x-pack/test/security_solution_api_integration/test_suites/genai/knowledge_base/entries/utils/auth/roles.ts b/x-pack/test/security_solution_api_integration/test_suites/genai/knowledge_base/entries/utils/auth/roles.ts index 9e81e7d11fffd..0d04c7b3f4fb0 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/genai/knowledge_base/entries/utils/auth/roles.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/genai/knowledge_base/entries/utils/auth/roles.ts @@ -40,7 +40,7 @@ export const securitySolutionOnlyAll: Role = { kibana: [ { feature: { - siem: ['all'], + siemV2: ['all'], securitySolutionAssistant: ['all'], securitySolutionAttackDiscovery: ['all'], aiAssistantManagementSelection: ['all'], @@ -60,7 +60,7 @@ export const securitySolutionOnlyAllSpace2: Role = { kibana: [ { feature: { - siem: ['all'], + siemV2: ['all'], securitySolutionAssistant: ['all'], securitySolutionAttackDiscovery: ['all'], aiAssistantManagementSelection: ['all'], @@ -80,7 +80,7 @@ export const securitySolutionOnlyRead: Role = { kibana: [ { feature: { - siem: ['read'], + siemV2: ['read'], securitySolutionAssistant: ['all'], securitySolutionAttackDiscovery: ['all'], aiAssistantManagementSelection: ['all'], @@ -100,7 +100,7 @@ export const securitySolutionOnlyReadSpace2: Role = { kibana: [ { feature: { - siem: ['read'], + siemV2: ['read'], securitySolutionAssistant: ['all'], securitySolutionAttackDiscovery: ['all'], aiAssistantManagementSelection: ['all'], @@ -123,7 +123,7 @@ export const securitySolutionOnlyAllSpacesAll: Role = { kibana: [ { feature: { - siem: ['all'], + siemV2: ['all'], securitySolutionAssistant: ['all'], securitySolutionAttackDiscovery: ['all'], aiAssistantManagementSelection: ['all'], @@ -148,7 +148,7 @@ export const securitySolutionOnlyAllSpacesAllWithReadESIndices: Role = { kibana: [ { feature: { - siem: ['all'], + siemV2: ['all'], securitySolutionAssistant: ['all'], securitySolutionAttackDiscovery: ['all'], aiAssistantManagementSelection: ['all'], @@ -168,7 +168,7 @@ export const securitySolutionOnlyReadSpacesAll: Role = { kibana: [ { feature: { - siem: ['read'], + siemV2: ['read'], securitySolutionAssistant: ['all'], securitySolutionAttackDiscovery: ['all'], aiAssistantManagementSelection: ['all'], @@ -188,7 +188,7 @@ export const securitySolutionOnlyAllSpacesAllAssistantMinimalAll: Role = { kibana: [ { feature: { - siem: ['all'], + siemV2: ['all'], securitySolutionAssistant: ['minimal_all'], securitySolutionAttackDiscovery: ['all'], aiAssistantManagementSelection: ['all'], diff --git a/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/index.ts b/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/index.ts index b337faad85f07..57e42c95460aa 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/index.ts @@ -15,5 +15,7 @@ export default function ({ loadTestFile }: FtrProviderContextWithSpaces) { loadTestFile(require.resolve('./timeline_migrations')); loadTestFile(require.resolve('./import_timelines')); loadTestFile(require.resolve('./install_prepackaged_timelines')); + loadTestFile(require.resolve('./timeline_privileges')); + loadTestFile(require.resolve('./notes_privileges')); }); } diff --git a/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/notes_privileges.ts b/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/notes_privileges.ts new file mode 100644 index 0000000000000..f0f7c36b924f3 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/notes_privileges.ts @@ -0,0 +1,119 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContextWithSpaces } from '../../../../ftr_provider_context_with_spaces'; +import { createNote, deleteNote, getNote } from '../../utils/notes'; +import * as users from '../../../../config/privileges/users'; +import { roles } from '../../../../config/privileges/roles'; + +const canOnlyReadUsers = [users.secReadV1User, users.secNotesReadUser]; +const canWriteUsers = [users.secAllV1User, users.secNotesAllUser]; +const canWriteOrReadUsers = [...canOnlyReadUsers, ...canWriteUsers]; +const cannotAccessUsers = [users.secNoneV1User, users.secNotesNoneUser]; +const cannotWriteUsers = [...canOnlyReadUsers, ...cannotAccessUsers]; + +export default function ({ getService }: FtrProviderContextWithSpaces) { + const utils = getService('securitySolutionUtils'); + const config = getService('config'); + const isServerless = config.get('serverless'); + const isEss = !isServerless; + + describe('Notes privileges', () => { + before(async () => { + if (isEss) { + await Promise.all( + roles.map((role) => { + return utils.createRole(role.name, role); + }) + ); + await Promise.all( + users.allUsers.map((user) => { + return utils.createUser(user); + }) + ); + } + }); + after(async () => { + if (isEss) { + await utils.deleteUsers(users.allUsers.map((user) => user.username)); + await utils.deleteRoles(roles.map((role) => role.name)); + } + }); + afterEach(async () => { + await utils.cleanUpCustomRole(); + }); + + describe('read notes', () => { + let getNoteId = () => ''; + before(async () => { + const superTest = await utils.createSuperTestWithUser(users.secNotesAllUser); + const { + body: { noteId }, + } = await createNote(superTest, { text: 'test', documentId: '123' }); + getNoteId = () => noteId; + }); + + canWriteOrReadUsers.forEach((user) => { + it(`user "${user.username}" can read notes`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + await getNote(superTest, getNoteId()).expect(200); + }); + }); + + cannotAccessUsers.forEach((user) => { + it(`user "${user.username}" cannot read notes`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + await getNote(superTest, getNoteId()).expect(403); + }); + }); + }); + + describe('create notes', () => { + canWriteUsers.forEach((user) => { + it(`user "${user.username}" can create notes`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + const { status } = await createNote(superTest, { text: 'test', documentId: '123' }); + expect(status).to.be(200); + }); + }); + + cannotWriteUsers.forEach((user) => { + it(`user "${user.username}" cannot create notes`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + const { status } = await createNote(superTest, { text: 'test', documentId: '123' }); + expect(status).to.be(403); + }); + }); + }); + + describe('delete notes', () => { + let getNoteId = () => ''; + before(async () => { + const superTest = await utils.createSuperTestWithUser(users.secNotesAllUser); + const { + body: { noteId }, + } = await createNote(superTest, { text: 'test', documentId: '123' }); + getNoteId = () => noteId; + }); + + canWriteUsers.forEach((user) => { + it(`user "${user.username}" can delete notes`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + await deleteNote(superTest, getNoteId()).expect(200); + }); + }); + + cannotWriteUsers.forEach((user) => { + it(`user "${user.username}" cannot delete notes`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + await deleteNote(superTest, getNoteId()).expect(403); + }); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/timeline_privileges.ts b/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/timeline_privileges.ts new file mode 100644 index 0000000000000..7ee34ef482ec0 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/timeline_privileges.ts @@ -0,0 +1,274 @@ +/* + * 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 expect from '@kbn/expect'; +import { CreateTimelinesResponse } from '@kbn/security-solution-plugin/common/api/timeline'; +import { FtrProviderContextWithSpaces } from '../../../../ftr_provider_context_with_spaces'; +import { + getTimelines, + createBasicTimeline, + deleteTimeline, + patchTimeline, + favoriteTimeline, + pinEvent, + copyTimeline, + resolveTimeline, + installPrepackedTimelines, +} from '../../utils/timelines'; +import * as users from '../../../../config/privileges/users'; +import { roles } from '../../../../config/privileges/roles'; + +const canOnlyReadUsers = [users.secReadV1User, users.secTimelineReadUser]; +const canWriteUsers = [users.secAllV1User, users.secTimelineAllUser]; +const canWriteOrReadUsers = [...canOnlyReadUsers, ...canWriteUsers]; +const cannotAccessUsers = [users.secNoneV1User, users.secTimelineNoneUser]; +const cannotWriteUsers = [...canOnlyReadUsers, ...cannotAccessUsers]; + +export default function ({ getService }: FtrProviderContextWithSpaces) { + const utils = getService('securitySolutionUtils'); + const config = getService('config'); + const isServerless = config.get('serverless'); + const isEss = !isServerless; + + describe('Timeline privileges', () => { + before(async () => { + if (isEss) { + await Promise.all( + roles.map((role) => { + return utils.createRole(role.name, role); + }) + ); + await Promise.all( + users.allUsers.map((user) => { + return utils.createUser(user); + }) + ); + } + }); + after(async () => { + if (isEss) { + await utils.deleteUsers(users.allUsers.map((user) => user.username)); + await utils.deleteRoles(roles.map((role) => role.name)); + } + }); + afterEach(async () => { + await utils.cleanUpCustomRole(); + }); + + describe('read timelines', () => { + canWriteOrReadUsers.forEach((user) => { + it(`user "${user.username}" can read timelines`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + await getTimelines(superTest).expect(200); + }); + }); + + cannotAccessUsers.forEach((user) => { + it(`user "${user.username}" cannot read timelines`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + await getTimelines(superTest).expect(403); + }); + }); + }); + + describe('resolve timelines', () => { + let getTimelineId = () => ''; + before(async () => { + const superTest = await utils.createSuperTestWithUser(users.secTimelineAllUser); + const { + body: { savedObjectId }, + } = await createBasicTimeline(superTest, 'test timeline'); + getTimelineId = () => savedObjectId; + }); + canWriteOrReadUsers.forEach((user) => { + it(`user "${user.username}" can resolve timelines`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + await resolveTimeline(superTest, getTimelineId()).expect(200); + }); + }); + + cannotAccessUsers.forEach((user) => { + it(`user "${user.username}" cannot resolve timelines`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + await resolveTimeline(superTest, getTimelineId()).expect(403); + }); + }); + }); + + describe('create and delete timelines', () => { + canWriteUsers.forEach((user) => { + it(`user "${user.username}" can create and delete timelines`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + + const createResponse = await createBasicTimeline(superTest, 'test timeline'); + expect(createResponse.status).to.be(200); + + await deleteTimeline(superTest, createResponse.body.savedObjectId).expect(200); + }); + }); + + describe('insufficient privileges', () => { + let getTimelineToDeleteId = () => ''; + before(async () => { + // create a timeline with a privileged user + const privilegedSuperTest = await utils.createSuperTestWithUser(users.secTimelineAllUser); + const { + body: { savedObjectId: timelineId }, + } = await createBasicTimeline(privilegedSuperTest, 'test timeline'); + getTimelineToDeleteId = () => timelineId; + }); + + cannotWriteUsers.forEach((user) => { + it(`user "${user.username}" cannot create timelines`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + const createResponse = await createBasicTimeline(superTest, 'test timeline'); + expect(createResponse.status).to.be(403); + }); + + it(`user "${user.username}" cannot delete timelines`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + await deleteTimeline(superTest, getTimelineToDeleteId()).expect(403); + }); + }); + }); + }); + + describe('update timelines', () => { + canWriteUsers.forEach((user) => { + it(`user "${user.username}" can update timelines`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + const { + body: { savedObjectId: timelineId, version }, + } = await createBasicTimeline(superTest, 'test timeline'); + + await patchTimeline(superTest, timelineId, version, { + title: 'updated title', + }).expect(200); + }); + }); + + describe('insufficient privileges', () => { + let getTimelineId = () => ''; + let getVersion = () => ''; + before(async () => { + const superTest = await utils.createSuperTestWithUser(users.secTimelineAllUser); + const { + body: { savedObjectId, version }, + } = await createBasicTimeline(superTest, 'test timeline'); + getTimelineId = () => savedObjectId; + getVersion = () => version; + }); + cannotWriteUsers.forEach((user) => { + it(`user "${user.username}" cannot create timelines`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + await patchTimeline(superTest, getTimelineId(), getVersion(), { + title: 'updated title', + }).expect(403); + }); + }); + }); + }); + + describe('favorite/unfavorite timelines', () => { + let getTimelineId = () => ''; + before(async () => { + const superTest = await utils.createSuperTestWithUser(users.secTimelineAllUser); + const { + body: { savedObjectId }, + } = await createBasicTimeline(superTest, 'test timeline'); + getTimelineId = () => savedObjectId; + }); + canWriteUsers.forEach((user) => { + it(`user "${user.username}" can favorite/unfavorite timelines`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + await favoriteTimeline(superTest, getTimelineId()).expect(200); + + // unfavorite + await favoriteTimeline(superTest, getTimelineId()).expect(200); + }); + }); + + cannotWriteUsers.forEach((user) => { + it(`user "${user.username}" cannot favorite/unfavorite timelines`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + + await favoriteTimeline(superTest, getTimelineId()).expect(403); + }); + }); + }); + + describe('pin/unpin events', () => { + let getTimelineId = () => ''; + const eventId = 'anId'; + before(async () => { + const superTest = await utils.createSuperTestWithUser(users.secTimelineAllUser); + const { + body: { savedObjectId }, + } = await createBasicTimeline(superTest, 'test timeline'); + getTimelineId = () => savedObjectId; + }); + canWriteUsers.forEach((user) => { + it(`user "${user.username}" can pin/unpin events`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + await pinEvent(superTest, getTimelineId(), eventId).expect(200); + + // unpin + await pinEvent(superTest, getTimelineId(), eventId).expect(200); + }); + }); + + cannotWriteUsers.forEach((user) => { + it(`user "${user.username}" cannot pin/unpin events`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + + await pinEvent(superTest, getTimelineId(), eventId).expect(403); + }); + }); + }); + + describe('copy timeline', () => { + let getTimeline: () => CreateTimelinesResponse = () => + ({} as unknown as CreateTimelinesResponse); + before(async () => { + const superTest = await utils.createSuperTestWithUser(users.secTimelineAllUser); + const { body } = await createBasicTimeline(superTest, 'test timeline'); + getTimeline = () => body; + }); + canWriteUsers.forEach((user) => { + it(`user "${user.username}" can copy timeline`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + const timeline = getTimeline(); + await copyTimeline(superTest, timeline.savedObjectId, timeline).expect(200); + }); + }); + + cannotWriteUsers.forEach((user) => { + it(`user "${user.username}" cannot copy timeline`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + const timeline = getTimeline(); + await copyTimeline(superTest, timeline.savedObjectId, timeline).expect(403); + }); + }); + }); + + describe('install prepackaged timelines', () => { + canWriteUsers.forEach((user) => { + it(`user "${user.username}" can install prepackaged timelines`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + await installPrepackedTimelines(superTest).expect(200); + }); + }); + + cannotWriteUsers.forEach((user) => { + it(`user "${user.username}" cannot install prepackaged timelines`, async () => { + const superTest = await utils.createSuperTestWithUser(user); + await installPrepackedTimelines(superTest).expect(403); + }); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/notes.ts b/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/notes.ts index 84db87aefb8f7..57599ca28aef8 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/notes.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/notes.ts @@ -58,3 +58,15 @@ export const createNote = async ( note: note.text, }, } as PersistNoteRouteRequestBody); + +export const getNote = (supertest: SuperTest.Agent, noteId: string) => + supertest + .get(`${NOTE_URL}?noteId=${noteId}`) + .set('kbn-xsrf', 'true') + .set('elastic-api-version', '2023-10-31'); + +export const deleteNote = (supertest: SuperTest.Agent, noteId: string) => + supertest.delete(NOTE_URL).set('kbn-xsrf', 'true').set('elastic-api-version', '2023-10-31').send({ + noteId, + noteIds: null, + }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/timelines.ts b/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/timelines.ts index 4a5d849e8565d..3b63b1a7b72fb 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/timelines.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/timelines.ts @@ -9,20 +9,26 @@ import type SuperTest from 'supertest'; import { v4 as uuidv4 } from 'uuid'; import { GetTimelinesResponse, + SavedTimeline, SavedTimelineWithSavedObjectId, TimelineTypeEnum, } from '@kbn/security-solution-plugin/common/api/timeline'; -import { TIMELINE_URL } from '@kbn/security-solution-plugin/common/constants'; +import { + TIMELINE_URL, + TIMELINES_URL, + TIMELINE_FAVORITE_URL, + PINNED_EVENT_URL, + TIMELINE_COPY_URL, + TIMELINE_RESOLVE_URL, + TIMELINE_PREPACKAGED_URL, +} from '@kbn/security-solution-plugin/common/constants'; /** * Deletes the first 100 timelines. * This works in ess, serverless and on the MKI environments as it avoids having to look at hidden indexes. */ export const deleteTimelines = async (supertest: SuperTest.Agent): Promise => { - const response = await supertest - .get('/api/timelines') - .set('kbn-xsrf', 'true') - .set('elastic-api-version', '2023-10-31'); + const response = await getTimelines(supertest); const { timeline: timelines } = response.body as GetTimelinesResponse; await supertest @@ -35,6 +41,26 @@ export const deleteTimelines = async (supertest: SuperTest.Agent): Promise }); }; +export const deleteTimeline = (supertest: SuperTest.Agent, savedObjectId: string) => + supertest + .delete(TIMELINE_URL) + .set('kbn-xsrf', 'true') + .send({ + savedObjectIds: [savedObjectId], + }); + +export const patchTimeline = ( + supertest: SuperTest.Agent, + timelineId: string, + version: string, + timelineObj: unknown +) => + supertest.patch(TIMELINE_URL).set('kbn-xsrf', 'true').send({ + timelineId, + version, + timeline: timelineObj, + }); + export const createBasicTimeline = async (supertest: SuperTest.Agent, titleToSaved: string) => await supertest .post(TIMELINE_URL) @@ -64,3 +90,47 @@ export const createBasicTimelineTemplate = async ( timelineType: TimelineTypeEnum.template, }, }); + +export const getTimelines = (supertest: SuperTest.Agent) => + supertest.get(TIMELINES_URL).set('kbn-xsrf', 'true').set('elastic-api-version', '2023-10-31'); + +export const resolveTimeline = (supertest: SuperTest.Agent, timelineId: string) => + supertest + .get(`${TIMELINE_RESOLVE_URL}?id=${timelineId}`) + .set('kbn-xsrf', 'true') + .set('elastic-api-version', '2023-10-31'); + +export const favoriteTimeline = (supertest: SuperTest.Agent, timelineId: string) => + supertest + .patch(TIMELINE_FAVORITE_URL) + .set('kbn-xsrf', 'true') + .set('elastic-api-version', '2023-10-31') + .send({ + timelineId, + templateTimelineId: null, + templateTimelineVersion: null, + timelineType: null, + }); + +export const pinEvent = (supertest: SuperTest.Agent, timelineId: string, eventId: string) => + supertest + .patch(PINNED_EVENT_URL) + .set('kbn-xsrf', 'true') + .set('elastic-api-version', '2023-10-31') + .send({ + timelineId, + eventId, + }); + +export const copyTimeline = ( + supertest: SuperTest.Agent, + timelineId: string, + timelineObj: SavedTimeline +) => + supertest.post(TIMELINE_COPY_URL).set('kbn-xsrf', 'true').set('elastic-api-version', '1').send({ + timelineIdToCopy: timelineId, + timeline: timelineObj, + }); + +export const installPrepackedTimelines = (supertest: SuperTest.Agent) => + supertest.post(TIMELINE_PREPACKAGED_URL).set('kbn-xsrf', 'true').send(); diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/read_list_privileges.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/read_list_privileges.ts index 0ab363ce961d0..22cfa186d6531 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/read_list_privileges.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/read_list_privileges.ts @@ -38,7 +38,7 @@ export default ({ getService }: FtrProviderContextWithSpaces) => { { feature: { dashboard: ['all'], - siem: ['all', 'read'], + siemV2: ['all', 'read'], }, spaces: [space1Id], }, diff --git a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/rules.ts b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/rules.ts index dba16076fcc38..b2247a97c6381 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/rules.ts @@ -47,7 +47,8 @@ const migrationRuleDocument: RuleMigrationDocument = { translation_result: 'partial', elastic_rule: { severity: 'low', - integration_id: '', + risk_score: 21, + integration_ids: [''], query: 'FROM [indexPattern]\n| STATS lastTime = max(_time), tag = values(tag), count BY dest, user, app', description: diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/entity_analytics/dashboards/enable_risk_score_redirect.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/entity_analytics/dashboards/enable_risk_score_redirect.cy.ts index 40d5623f114fd..588263aa42c6b 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/entity_analytics/dashboards/enable_risk_score_redirect.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/entity_analytics/dashboards/enable_risk_score_redirect.cy.ts @@ -14,7 +14,8 @@ import { clickEnableRiskScore } from '../../../tasks/risk_scores'; import { ENTITY_ANALYTICS_URL } from '../../../urls/navigation'; import { PAGE_TITLE } from '../../../screens/entity_analytics_management'; -describe( +// Failing: See https://github.com/elastic/kibana/issues/206580 +describe.skip( 'Enable risk scores from dashboard', { tags: ['@ess', '@serverless'], diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/privileges.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/privileges.cy.ts new file mode 100644 index 0000000000000..0f31dc585f127 --- /dev/null +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/privileges.cy.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 { ROLES } from '@kbn/security-solution-plugin/common/test'; + +import { login } from '../../../tasks/login'; +import { visitWithTimeRange } from '../../../tasks/navigation'; + +import { hostsUrl } from '../../../urls/navigation'; +import { ACTIVE_TIMELINE_BOTTOM_BAR } from '../../../screens/timeline'; +import { TIMELINES } from '../../../screens/security_header'; +import { + NAV_SEARCH_INPUT, + NAV_SEARCH_NO_RESULTS, + NAV_SEARCH_RESULTS, +} from '../../../screens/search_bar'; + +describe('Privileges', { tags: ['@ess', '@skipInServerless'] }, () => { + describe('Timeline', () => { + it('should not show timeline elements for users with insufficient privileges', () => { + login(ROLES.timeline_none); + visitWithTimeRange(hostsUrl('allHosts')); + // no timeline bottom bar + cy.get(ACTIVE_TIMELINE_BOTTOM_BAR).should('not.exist'); + // no link to the timelines page + cy.get(TIMELINES).should('not.exist'); + // no search result for timeline in the nav search + cy.get(NAV_SEARCH_INPUT).type('Timelines'); + cy.get(NAV_SEARCH_NO_RESULTS).should('exist'); + }); + + it('should show timeline elements for users with sufficient privileges', () => { + login(); + visitWithTimeRange(hostsUrl('allHosts')); + cy.get(ACTIVE_TIMELINE_BOTTOM_BAR).should('exist'); + cy.get(TIMELINES).should('exist'); + cy.get(NAV_SEARCH_INPUT).type('Timelines'); + cy.get(NAV_SEARCH_RESULTS).contains('Timelines'); + }); + }); + + // Somehow, these tests fail on CI... + describe.skip('Notes', () => { + it('should show notes in search for users with privileges', () => { + login(ROLES.t3_analyst); + visitWithTimeRange(hostsUrl('allHosts')); + cy.get(NAV_SEARCH_INPUT).focus(); + cy.get(NAV_SEARCH_INPUT).type('Notes'); + cy.get(NAV_SEARCH_RESULTS).contains('Notes'); + }); + + it('should not show notes in search for users with insufficient privileges', () => { + login(ROLES.notes_none); + visitWithTimeRange(hostsUrl('allHosts')); + // no search result for notes in the nav search + cy.get(NAV_SEARCH_INPUT).focus(); + cy.get(NAV_SEARCH_INPUT).type('Notes'); + cy.get(NAV_SEARCH_NO_RESULTS).should('exist'); + }); + }); +}); diff --git a/x-pack/test/security_solution_cypress/cypress/screens/alerts_detection_rules.ts b/x-pack/test/security_solution_cypress/cypress/screens/alerts_detection_rules.ts index e2ce41dee2847..f6f1bae56bfce 100644 --- a/x-pack/test/security_solution_cypress/cypress/screens/alerts_detection_rules.ts +++ b/x-pack/test/security_solution_cypress/cypress/screens/alerts_detection_rules.ts @@ -269,8 +269,8 @@ export const TIMELINE_TEMPLATE_VALUE = '[data-test-subj="timelineTemplatePropert export const INTERVAL_TITLE = '[data-test-subj="intervalPropertyTitle"]'; export const INTERVAL_VALUE = '[data-test-subj="intervalPropertyValue"]'; -export const FROM_TITLE = '[data-test-subj="fromPropertyTitle"]'; -export const FROM_VALUE = '[data-test-subj^="fromPropertyValue"]'; +export const LOOK_BACK_TITLE = '[data-test-subj="lookBackPropertyTitle"]'; +export const LOOK_BACK_VALUE = '[data-test-subj^="lookBackPropertyValue"]'; export const INDEX_TITLE = '[data-test-subj="indexPropertyTitle"]'; export const INDEX_VALUE_ITEM = '[data-test-subj="indexPropertyValueItem"]'; diff --git a/x-pack/test/security_solution_cypress/cypress/screens/search_bar.ts b/x-pack/test/security_solution_cypress/cypress/screens/search_bar.ts index 766f7da5f131f..cce6478cc6457 100644 --- a/x-pack/test/security_solution_cypress/cypress/screens/search_bar.ts +++ b/x-pack/test/security_solution_cypress/cypress/screens/search_bar.ts @@ -48,3 +48,9 @@ export const AUTO_SUGGEST_HOST_NAME_VALUE = `[data-test-subj='autocompleteSugges export const EDIT_AS_QUERY_DSL = getDataTestSubjectSelector('editQueryDSL'); export const KIBANA_CODE_EDITOR = getDataTestSubjectSelector('kibanaCodeEditor'); + +export const NAV_SEARCH_INPUT = '[data-test-subj="nav-search-input"]'; + +export const NAV_SEARCH_RESULTS = '[aria-label="Filter options"]'; + +export const NAV_SEARCH_NO_RESULTS = '[data-test-subj="nav-search-no-results"]'; diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules_preview.ts b/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules_preview.ts index c67ab29831075..9ae6c623a388f 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules_preview.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules_preview.ts @@ -14,6 +14,8 @@ import { } from '@kbn/security-solution-plugin/common/api/detection_engine/model/rule_schema'; import type { Filter } from '@kbn/es-query'; import type { PrebuiltRuleAsset } from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules'; +import { calcDateMathDiff } from '@kbn/securitysolution-utils/date_math'; +import { TimeDuration } from '@kbn/securitysolution-utils/time_duration'; import { ALERT_SUPPRESSION_DURATION_TITLE, ALERT_SUPPRESSION_DURATION_VALUE, @@ -42,8 +44,8 @@ import { FILTERS_TITLE, FILTERS_VALUE_ITEM, FLYOUT_CLOSE_BTN, - FROM_TITLE, - FROM_VALUE, + LOOK_BACK_TITLE, + LOOK_BACK_VALUE, INDEX_TITLE, INDEX_VALUE_ITEM, INSTALL_PREBUILT_RULE_PREVIEW, @@ -227,8 +229,15 @@ export const assertCommonPropertiesShown = (properties: Partial { diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/privileges.ts b/x-pack/test/security_solution_cypress/cypress/tasks/privileges.ts index bbbaaa1e240a6..0fd8e6f11b8be 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/privileges.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/privileges.ts @@ -62,7 +62,9 @@ export const secAll: Role = { kibana: [ { feature: { - siem: ['all'], + siemV2: ['all'], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], securitySolutionAssistant: ['all'], securitySolutionAttackDiscovery: ['all'], securitySolutionCases: ['all'], @@ -96,7 +98,9 @@ export const secReadCasesAll: Role = { kibana: [ { feature: { - siem: ['read'], + siemV2: ['read'], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], securitySolutionAssistant: ['all'], securitySolutionAttackDiscovery: ['all'], securitySolutionCases: ['all'], @@ -130,7 +134,9 @@ export const secAllCasesOnlyReadDelete: Role = { kibana: [ { feature: { - siem: ['all'], + siemV2: ['all'], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], securitySolutionAssistant: ['all'], securitySolutionAttackDiscovery: ['all'], securitySolutionCases: ['cases_read', 'cases_delete'], @@ -164,7 +170,9 @@ export const secAllCasesNoDelete: Role = { kibana: [ { feature: { - siem: ['all'], + siemV2: ['all'], + securitySolutionTimeline: ['all'], + securitySolutionNotes: ['all'], securitySolutionAssistant: ['all'], securitySolutionAttackDiscovery: ['all'], securitySolutionCases: ['minimal_all'], diff --git a/x-pack/test/security_solution_cypress/cypress/tsconfig.json b/x-pack/test/security_solution_cypress/cypress/tsconfig.json index 67f8e878bc6fe..20064862b1389 100644 --- a/x-pack/test/security_solution_cypress/cypress/tsconfig.json +++ b/x-pack/test/security_solution_cypress/cypress/tsconfig.json @@ -46,5 +46,6 @@ "@kbn/elastic-assistant-common", "@kbn/cloud-security-posture-common", "@kbn/security-plugin-types-common", + "@kbn/securitysolution-utils" ] } diff --git a/x-pack/test/session_view/basic/tests/index.ts b/x-pack/test/session_view/basic/tests/index.ts index 71a28bb106186..d471882963566 100644 --- a/x-pack/test/session_view/basic/tests/index.ts +++ b/x-pack/test/session_view/basic/tests/index.ts @@ -57,7 +57,7 @@ export const securitySolutionOnlyReadSpacesAll: Role = { kibana: [ { feature: { - siem: ['read'], + siemV2: ['read'], }, spaces: ['*'], }, diff --git a/x-pack/test/spaces_api_integration/common/suites/create.ts b/x-pack/test/spaces_api_integration/common/suites/create.ts index d84945fbfe032..5599d065eb93c 100644 --- a/x-pack/test/spaces_api_integration/common/suites/create.ts +++ b/x-pack/test/spaces_api_integration/common/suites/create.ts @@ -86,7 +86,10 @@ export function createTestSuiteFactory(esArchiver: any, supertest: SuperTest) 'securitySolutionAttackDiscovery', 'securitySolutionCases', 'securitySolutionCasesV2', + 'securitySolutionNotes', + 'securitySolutionTimeline', 'siem', + 'siemV2', 'slo', 'uptime', ], diff --git a/x-pack/test/spaces_api_integration/common/suites/get_all.ts b/x-pack/test/spaces_api_integration/common/suites/get_all.ts index 9d51cbb12e469..9f4abd8001f6d 100644 --- a/x-pack/test/spaces_api_integration/common/suites/get_all.ts +++ b/x-pack/test/spaces_api_integration/common/suites/get_all.ts @@ -85,7 +85,10 @@ const ALL_SPACE_RESULTS: Space[] = [ 'securitySolutionAttackDiscovery', 'securitySolutionCases', 'securitySolutionCasesV2', + 'securitySolutionNotes', + 'securitySolutionTimeline', 'siem', + 'siemV2', 'slo', 'uptime', ], diff --git a/x-pack/test/spaces_api_integration/spaces_only/telemetry/telemetry.ts b/x-pack/test/spaces_api_integration/spaces_only/telemetry/telemetry.ts index 1af3b0e593e06..99f1985b8164f 100644 --- a/x-pack/test/spaces_api_integration/spaces_only/telemetry/telemetry.ts +++ b/x-pack/test/spaces_api_integration/spaces_only/telemetry/telemetry.ts @@ -88,10 +88,13 @@ export default function ({ getService }: FtrProviderContext) { searchInferenceEndpoints: 0, searchPlayground: 0, siem: 0, + siemV2: 0, securitySolutionCases: 0, securitySolutionCasesV2: 0, securitySolutionAssistant: 0, securitySolutionAttackDiscovery: 0, + securitySolutionTimeline: 0, + securitySolutionNotes: 0, discover: 0, visualize: 0, dashboard: 0, diff --git a/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/migrations.ts b/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/migrations.ts index 31854652cbc67..6964e1a5a2ebc 100644 --- a/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/migrations.ts +++ b/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/migrations.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import type { TransportResult } from '@elastic/elasticsearch'; import { ConcreteTaskInstance, diff --git a/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/task_management.ts b/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/task_management.ts index 33c72ffd1de95..b05b617e6fb76 100644 --- a/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/task_management.ts +++ b/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/task_management.ts @@ -8,7 +8,7 @@ import moment from 'moment'; import { random } from 'lodash'; import expect from '@kbn/expect'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { taskMappings as TaskManagerMapping } from '@kbn/task-manager-plugin/server/saved_objects/mappings'; import { ConcreteTaskInstance, BulkUpdateTaskResult } from '@kbn/task-manager-plugin/server'; import { FtrProviderContext } from '../../ftr_provider_context'; diff --git a/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/task_priority.ts b/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/task_priority.ts index f8fc3f63987b9..3e20cec5fab93 100644 --- a/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/task_priority.ts +++ b/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/task_priority.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { ConcreteTaskInstance } from '@kbn/task-manager-plugin/server'; import { taskMappings as TaskManagerMapping } from '@kbn/task-manager-plugin/server/saved_objects/mappings'; import { asyncForEach } from '@kbn/std'; diff --git a/x-pack/test_serverless/api_integration/test_suites/security/platform_security/authorization.ts b/x-pack/test_serverless/api_integration/test_suites/security/platform_security/authorization.ts index 96452e95d6d34..5f3deb035cb27 100644 --- a/x-pack/test_serverless/api_integration/test_suites/security/platform_security/authorization.ts +++ b/x-pack/test_serverless/api_integration/test_suites/security/platform_security/authorization.ts @@ -30,7 +30,7 @@ export default function ({ getService }: FtrProviderContext) { // The following features are composed of other features in a way that is // specific to the security solution. - const compositeFeatureIds = ['dashboard', 'discover', 'reporting', 'siem']; + const compositeFeatureIds = ['dashboard', 'discover', 'reporting', 'siemV2']; const features = Object.fromEntries( Object.entries(body.features).filter(([key]) => compositeFeatureIds.includes(key)) @@ -195,18 +195,18 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:cloud/close_point_in_time", ], }, - "siem": Object { + "siemV2": Object { "actions_log_management_all": Array [ "login:", "api:securitySolution-writeActionsLogManagement", "api:securitySolution-readActionsLogManagement", - "ui:siem/writeActionsLogManagement", - "ui:siem/readActionsLogManagement", + "ui:siemV2/writeActionsLogManagement", + "ui:siemV2/readActionsLogManagement", ], "actions_log_management_read": Array [ "login:", "api:securitySolution-readActionsLogManagement", - "ui:siem/readActionsLogManagement", + "ui:siemV2/readActionsLogManagement", ], "all": Array [ "login:", @@ -281,30 +281,6 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:index-pattern/delete", "saved_object:index-pattern/bulk_delete", "saved_object:index-pattern/share_to_space", - "saved_object:siem-ui-timeline-note/bulk_get", - "saved_object:siem-ui-timeline-note/get", - "saved_object:siem-ui-timeline-note/find", - "saved_object:siem-ui-timeline-note/open_point_in_time", - "saved_object:siem-ui-timeline-note/close_point_in_time", - "saved_object:siem-ui-timeline-note/create", - "saved_object:siem-ui-timeline-note/bulk_create", - "saved_object:siem-ui-timeline-note/update", - "saved_object:siem-ui-timeline-note/bulk_update", - "saved_object:siem-ui-timeline-note/delete", - "saved_object:siem-ui-timeline-note/bulk_delete", - "saved_object:siem-ui-timeline-note/share_to_space", - "saved_object:siem-ui-timeline-pinned-event/bulk_get", - "saved_object:siem-ui-timeline-pinned-event/get", - "saved_object:siem-ui-timeline-pinned-event/find", - "saved_object:siem-ui-timeline-pinned-event/open_point_in_time", - "saved_object:siem-ui-timeline-pinned-event/close_point_in_time", - "saved_object:siem-ui-timeline-pinned-event/create", - "saved_object:siem-ui-timeline-pinned-event/bulk_create", - "saved_object:siem-ui-timeline-pinned-event/update", - "saved_object:siem-ui-timeline-pinned-event/bulk_update", - "saved_object:siem-ui-timeline-pinned-event/delete", - "saved_object:siem-ui-timeline-pinned-event/bulk_delete", - "saved_object:siem-ui-timeline-pinned-event/share_to_space", "saved_object:siem-detection-engine-rule-actions/bulk_get", "saved_object:siem-detection-engine-rule-actions/get", "saved_object:siem-detection-engine-rule-actions/find", @@ -329,18 +305,6 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:security-rule/delete", "saved_object:security-rule/bulk_delete", "saved_object:security-rule/share_to_space", - "saved_object:siem-ui-timeline/bulk_get", - "saved_object:siem-ui-timeline/get", - "saved_object:siem-ui-timeline/find", - "saved_object:siem-ui-timeline/open_point_in_time", - "saved_object:siem-ui-timeline/close_point_in_time", - "saved_object:siem-ui-timeline/create", - "saved_object:siem-ui-timeline/bulk_create", - "saved_object:siem-ui-timeline/update", - "saved_object:siem-ui-timeline/bulk_update", - "saved_object:siem-ui-timeline/delete", - "saved_object:siem-ui-timeline/bulk_delete", - "saved_object:siem-ui-timeline/share_to_space", "saved_object:endpoint:user-artifact-manifest/bulk_get", "saved_object:endpoint:user-artifact-manifest/get", "saved_object:endpoint:user-artifact-manifest/find", @@ -486,14 +450,14 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:cloud/find", "saved_object:cloud/open_point_in_time", "saved_object:cloud/close_point_in_time", - "ui:siem/show", - "ui:siem/crud", - "ui:siem/entity-analytics", - "ui:siem/investigation-guide", - "ui:siem/investigation-guide-interactions", - "ui:siem/threat-intelligence", - "ui:siem/showEndpointExceptions", - "ui:siem/crudEndpointExceptions", + "ui:siemV2/show", + "ui:siemV2/crud", + "ui:siemV2/entity-analytics", + "ui:siemV2/investigation-guide", + "ui:siemV2/investigation-guide-interactions", + "ui:siemV2/threat-intelligence", + "ui:siemV2/showEndpointExceptions", + "ui:siemV2/crudEndpointExceptions", "alerting:siem.notifications/siem/rule/get", "alerting:siem.notifications/siem/rule/getRuleState", "alerting:siem.notifications/siem/rule/getAlertSummary", @@ -959,39 +923,39 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:exception-list-agnostic/delete", "saved_object:exception-list-agnostic/bulk_delete", "saved_object:exception-list-agnostic/share_to_space", - "ui:siem/writeBlocklist", - "ui:siem/readBlocklist", + "ui:siemV2/writeBlocklist", + "ui:siemV2/readBlocklist", ], "blocklist_read": Array [ "login:", "api:lists-read", "api:lists-summary", "api:securitySolution-readBlocklist", - "ui:siem/readBlocklist", + "ui:siemV2/readBlocklist", ], "endpoint_exceptions_all": Array [ "login:", "api:securitySolution-showEndpointExceptions", "api:securitySolution-crudEndpointExceptions", - "ui:siem/showEndpointExceptions", - "ui:siem/crudEndpointExceptions", + "ui:siemV2/showEndpointExceptions", + "ui:siemV2/crudEndpointExceptions", ], "endpoint_exceptions_read": Array [ "login:", "api:securitySolution-showEndpointExceptions", - "ui:siem/showEndpointExceptions", + "ui:siemV2/showEndpointExceptions", ], "endpoint_list_all": Array [ "login:", "api:securitySolution-writeEndpointList", "api:securitySolution-readEndpointList", - "ui:siem/writeEndpointList", - "ui:siem/readEndpointList", + "ui:siemV2/writeEndpointList", + "ui:siemV2/readEndpointList", ], "endpoint_list_read": Array [ "login:", "api:securitySolution-readEndpointList", - "ui:siem/readEndpointList", + "ui:siemV2/readEndpointList", ], "event_filters_all": Array [ "login:", @@ -1012,32 +976,32 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:exception-list-agnostic/delete", "saved_object:exception-list-agnostic/bulk_delete", "saved_object:exception-list-agnostic/share_to_space", - "ui:siem/writeEventFilters", - "ui:siem/readEventFilters", + "ui:siemV2/writeEventFilters", + "ui:siemV2/readEventFilters", ], "event_filters_read": Array [ "login:", "api:lists-read", "api:lists-summary", "api:securitySolution-readEventFilters", - "ui:siem/readEventFilters", + "ui:siemV2/readEventFilters", ], "execute_operations_all": Array [ "login:", "api:securitySolution-writeExecuteOperations", - "ui:siem/writeExecuteOperations", + "ui:siemV2/writeExecuteOperations", ], "file_operations_all": Array [ "login:", "api:securitySolution-writeFileOperations", - "ui:siem/writeFileOperations", + "ui:siemV2/writeFileOperations", ], "host_isolation_all": Array [ "login:", "api:securitySolution-writeHostIsolationRelease", "api:securitySolution-writeHostIsolation", - "ui:siem/writeHostIsolationRelease", - "ui:siem/writeHostIsolation", + "ui:siemV2/writeHostIsolationRelease", + "ui:siemV2/writeHostIsolation", ], "host_isolation_exceptions_all": Array [ "login:", @@ -1060,10 +1024,10 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:exception-list-agnostic/delete", "saved_object:exception-list-agnostic/bulk_delete", "saved_object:exception-list-agnostic/share_to_space", - "ui:siem/readHostIsolationExceptions", - "ui:siem/deleteHostIsolationExceptions", - "ui:siem/accessHostIsolationExceptions", - "ui:siem/writeHostIsolationExceptions", + "ui:siemV2/readHostIsolationExceptions", + "ui:siemV2/deleteHostIsolationExceptions", + "ui:siemV2/accessHostIsolationExceptions", + "ui:siemV2/writeHostIsolationExceptions", ], "host_isolation_exceptions_read": Array [ "login:", @@ -1071,8 +1035,8 @@ export default function ({ getService }: FtrProviderContext) { "api:lists-summary", "api:securitySolution-readHostIsolationExceptions", "api:securitySolution-accessHostIsolationExceptions", - "ui:siem/readHostIsolationExceptions", - "ui:siem/accessHostIsolationExceptions", + "ui:siemV2/readHostIsolationExceptions", + "ui:siemV2/accessHostIsolationExceptions", ], "minimal_all": Array [ "login:", @@ -1145,30 +1109,6 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:index-pattern/delete", "saved_object:index-pattern/bulk_delete", "saved_object:index-pattern/share_to_space", - "saved_object:siem-ui-timeline-note/bulk_get", - "saved_object:siem-ui-timeline-note/get", - "saved_object:siem-ui-timeline-note/find", - "saved_object:siem-ui-timeline-note/open_point_in_time", - "saved_object:siem-ui-timeline-note/close_point_in_time", - "saved_object:siem-ui-timeline-note/create", - "saved_object:siem-ui-timeline-note/bulk_create", - "saved_object:siem-ui-timeline-note/update", - "saved_object:siem-ui-timeline-note/bulk_update", - "saved_object:siem-ui-timeline-note/delete", - "saved_object:siem-ui-timeline-note/bulk_delete", - "saved_object:siem-ui-timeline-note/share_to_space", - "saved_object:siem-ui-timeline-pinned-event/bulk_get", - "saved_object:siem-ui-timeline-pinned-event/get", - "saved_object:siem-ui-timeline-pinned-event/find", - "saved_object:siem-ui-timeline-pinned-event/open_point_in_time", - "saved_object:siem-ui-timeline-pinned-event/close_point_in_time", - "saved_object:siem-ui-timeline-pinned-event/create", - "saved_object:siem-ui-timeline-pinned-event/bulk_create", - "saved_object:siem-ui-timeline-pinned-event/update", - "saved_object:siem-ui-timeline-pinned-event/bulk_update", - "saved_object:siem-ui-timeline-pinned-event/delete", - "saved_object:siem-ui-timeline-pinned-event/bulk_delete", - "saved_object:siem-ui-timeline-pinned-event/share_to_space", "saved_object:siem-detection-engine-rule-actions/bulk_get", "saved_object:siem-detection-engine-rule-actions/get", "saved_object:siem-detection-engine-rule-actions/find", @@ -1193,18 +1133,6 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:security-rule/delete", "saved_object:security-rule/bulk_delete", "saved_object:security-rule/share_to_space", - "saved_object:siem-ui-timeline/bulk_get", - "saved_object:siem-ui-timeline/get", - "saved_object:siem-ui-timeline/find", - "saved_object:siem-ui-timeline/open_point_in_time", - "saved_object:siem-ui-timeline/close_point_in_time", - "saved_object:siem-ui-timeline/create", - "saved_object:siem-ui-timeline/bulk_create", - "saved_object:siem-ui-timeline/update", - "saved_object:siem-ui-timeline/bulk_update", - "saved_object:siem-ui-timeline/delete", - "saved_object:siem-ui-timeline/bulk_delete", - "saved_object:siem-ui-timeline/share_to_space", "saved_object:endpoint:user-artifact-manifest/bulk_get", "saved_object:endpoint:user-artifact-manifest/get", "saved_object:endpoint:user-artifact-manifest/find", @@ -1350,12 +1278,12 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:cloud/find", "saved_object:cloud/open_point_in_time", "saved_object:cloud/close_point_in_time", - "ui:siem/show", - "ui:siem/crud", - "ui:siem/entity-analytics", - "ui:siem/investigation-guide", - "ui:siem/investigation-guide-interactions", - "ui:siem/threat-intelligence", + "ui:siemV2/show", + "ui:siemV2/crud", + "ui:siemV2/entity-analytics", + "ui:siemV2/investigation-guide", + "ui:siemV2/investigation-guide-interactions", + "ui:siemV2/threat-intelligence", "alerting:siem.notifications/siem/rule/get", "alerting:siem.notifications/siem/rule/getRuleState", "alerting:siem.notifications/siem/rule/getAlertSummary", @@ -1836,16 +1764,6 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:index-pattern/find", "saved_object:index-pattern/open_point_in_time", "saved_object:index-pattern/close_point_in_time", - "saved_object:siem-ui-timeline-note/bulk_get", - "saved_object:siem-ui-timeline-note/get", - "saved_object:siem-ui-timeline-note/find", - "saved_object:siem-ui-timeline-note/open_point_in_time", - "saved_object:siem-ui-timeline-note/close_point_in_time", - "saved_object:siem-ui-timeline-pinned-event/bulk_get", - "saved_object:siem-ui-timeline-pinned-event/get", - "saved_object:siem-ui-timeline-pinned-event/find", - "saved_object:siem-ui-timeline-pinned-event/open_point_in_time", - "saved_object:siem-ui-timeline-pinned-event/close_point_in_time", "saved_object:siem-detection-engine-rule-actions/bulk_get", "saved_object:siem-detection-engine-rule-actions/get", "saved_object:siem-detection-engine-rule-actions/find", @@ -1856,11 +1774,6 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:security-rule/find", "saved_object:security-rule/open_point_in_time", "saved_object:security-rule/close_point_in_time", - "saved_object:siem-ui-timeline/bulk_get", - "saved_object:siem-ui-timeline/get", - "saved_object:siem-ui-timeline/find", - "saved_object:siem-ui-timeline/open_point_in_time", - "saved_object:siem-ui-timeline/close_point_in_time", "saved_object:endpoint:user-artifact-manifest/bulk_get", "saved_object:endpoint:user-artifact-manifest/get", "saved_object:endpoint:user-artifact-manifest/find", @@ -1936,11 +1849,11 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:cloud/find", "saved_object:cloud/open_point_in_time", "saved_object:cloud/close_point_in_time", - "ui:siem/show", - "ui:siem/entity-analytics", - "ui:siem/investigation-guide", - "ui:siem/investigation-guide-interactions", - "ui:siem/threat-intelligence", + "ui:siemV2/show", + "ui:siemV2/entity-analytics", + "ui:siemV2/investigation-guide", + "ui:siemV2/investigation-guide-interactions", + "ui:siemV2/threat-intelligence", "alerting:siem.notifications/siem/rule/get", "alerting:siem.notifications/siem/rule/getRuleState", "alerting:siem.notifications/siem/rule/getAlertSummary", @@ -2155,8 +2068,8 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:policy-settings-protection-updates-note/delete", "saved_object:policy-settings-protection-updates-note/bulk_delete", "saved_object:policy-settings-protection-updates-note/share_to_space", - "ui:siem/writePolicyManagement", - "ui:siem/readPolicyManagement", + "ui:siemV2/writePolicyManagement", + "ui:siemV2/readPolicyManagement", ], "policy_management_read": Array [ "login:", @@ -2166,12 +2079,12 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:policy-settings-protection-updates-note/find", "saved_object:policy-settings-protection-updates-note/open_point_in_time", "saved_object:policy-settings-protection-updates-note/close_point_in_time", - "ui:siem/readPolicyManagement", + "ui:siemV2/readPolicyManagement", ], "process_operations_all": Array [ "login:", "api:securitySolution-writeProcessOperations", - "ui:siem/writeProcessOperations", + "ui:siemV2/writeProcessOperations", ], "read": Array [ "login:", @@ -2208,16 +2121,6 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:index-pattern/find", "saved_object:index-pattern/open_point_in_time", "saved_object:index-pattern/close_point_in_time", - "saved_object:siem-ui-timeline-note/bulk_get", - "saved_object:siem-ui-timeline-note/get", - "saved_object:siem-ui-timeline-note/find", - "saved_object:siem-ui-timeline-note/open_point_in_time", - "saved_object:siem-ui-timeline-note/close_point_in_time", - "saved_object:siem-ui-timeline-pinned-event/bulk_get", - "saved_object:siem-ui-timeline-pinned-event/get", - "saved_object:siem-ui-timeline-pinned-event/find", - "saved_object:siem-ui-timeline-pinned-event/open_point_in_time", - "saved_object:siem-ui-timeline-pinned-event/close_point_in_time", "saved_object:siem-detection-engine-rule-actions/bulk_get", "saved_object:siem-detection-engine-rule-actions/get", "saved_object:siem-detection-engine-rule-actions/find", @@ -2228,11 +2131,6 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:security-rule/find", "saved_object:security-rule/open_point_in_time", "saved_object:security-rule/close_point_in_time", - "saved_object:siem-ui-timeline/bulk_get", - "saved_object:siem-ui-timeline/get", - "saved_object:siem-ui-timeline/find", - "saved_object:siem-ui-timeline/open_point_in_time", - "saved_object:siem-ui-timeline/close_point_in_time", "saved_object:endpoint:user-artifact-manifest/bulk_get", "saved_object:endpoint:user-artifact-manifest/get", "saved_object:endpoint:user-artifact-manifest/find", @@ -2308,12 +2206,12 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:cloud/find", "saved_object:cloud/open_point_in_time", "saved_object:cloud/close_point_in_time", - "ui:siem/show", - "ui:siem/entity-analytics", - "ui:siem/investigation-guide", - "ui:siem/investigation-guide-interactions", - "ui:siem/threat-intelligence", - "ui:siem/showEndpointExceptions", + "ui:siemV2/show", + "ui:siemV2/entity-analytics", + "ui:siemV2/investigation-guide", + "ui:siemV2/investigation-guide-interactions", + "ui:siemV2/threat-intelligence", + "ui:siemV2/showEndpointExceptions", "alerting:siem.notifications/siem/rule/get", "alerting:siem.notifications/siem/rule/getRuleState", "alerting:siem.notifications/siem/rule/getAlertSummary", @@ -2515,7 +2413,7 @@ export default function ({ getService }: FtrProviderContext) { "scan_operations_all": Array [ "login:", "api:securitySolution-writeScanOperations", - "ui:siem/writeScanOperations", + "ui:siemV2/writeScanOperations", ], "trusted_applications_all": Array [ "login:", @@ -2536,15 +2434,15 @@ export default function ({ getService }: FtrProviderContext) { "saved_object:exception-list-agnostic/delete", "saved_object:exception-list-agnostic/bulk_delete", "saved_object:exception-list-agnostic/share_to_space", - "ui:siem/writeTrustedApplications", - "ui:siem/readTrustedApplications", + "ui:siemV2/writeTrustedApplications", + "ui:siemV2/readTrustedApplications", ], "trusted_applications_read": Array [ "login:", "api:lists-read", "api:lists-summary", "api:securitySolution-readTrustedApplications", - "ui:siem/readTrustedApplications", + "ui:siemV2/readTrustedApplications", ], }, } diff --git a/x-pack/test_serverless/functional/page_objects/svl_search_index_detail_page.ts b/x-pack/test_serverless/functional/page_objects/svl_search_index_detail_page.ts index 17821c7dfe73b..3e0a9da0744a9 100644 --- a/x-pack/test_serverless/functional/page_objects/svl_search_index_detail_page.ts +++ b/x-pack/test_serverless/functional/page_objects/svl_search_index_detail_page.ts @@ -221,20 +221,6 @@ export function SvlSearchIndexDetailPageProvider({ getService }: FtrProviderCont ); }, - async expectSampleDocumentsWithCustomMappings() { - await browser.refresh(); - await testSubjects.existOrFail('ingestDataCodeExample-code-block'); - expect(await testSubjects.getVisibleText('ingestDataCodeExample-code-block')).to.contain( - 'Example text 1' - ); - expect(await testSubjects.getVisibleText('ingestDataCodeExample-code-block')).to.contain( - 'Example text 2' - ); - expect(await testSubjects.getVisibleText('ingestDataCodeExample-code-block')).to.contain( - 'Example text 3' - ); - }, - async clickFirstDocumentDeleteAction() { await testSubjects.existOrFail('documentMetadataButton'); await testSubjects.click('documentMetadataButton'); diff --git a/x-pack/test_serverless/functional/services/ml/observability_navigation.ts b/x-pack/test_serverless/functional/services/ml/observability_navigation.ts index 5181d4981321a..83bfc80c462f5 100644 --- a/x-pack/test_serverless/functional/services/ml/observability_navigation.ts +++ b/x-pack/test_serverless/functional/services/ml/observability_navigation.ts @@ -26,5 +26,11 @@ export function MachineLearningNavigationProviderObservability({ async navigateToAnomalyDetection() { await navigateToArea('anomalyDetection'); }, + async navigateToMemoryUsage() { + await navigateToArea('memoryUsage'); + }, + async navigateToNotifications() { + await navigateToArea('notifications'); + }, }; } diff --git a/x-pack/test_serverless/functional/services/ml/security_navigation.ts b/x-pack/test_serverless/functional/services/ml/security_navigation.ts index 17ebe65b45194..70db8900b93e4 100644 --- a/x-pack/test_serverless/functional/services/ml/security_navigation.ts +++ b/x-pack/test_serverless/functional/services/ml/security_navigation.ts @@ -28,5 +28,11 @@ export function MachineLearningNavigationProviderSecurity({ getService }: FtrPro async navigateToTrainedModels() { await navigateToArea('nodesOverview'); }, + async navigateToMemoryUsage() { + await navigateToArea('memoryUsage'); + }, + async navigateToNotifications() { + await navigateToArea('notifications'); + }, }; } diff --git a/x-pack/test_serverless/functional/test_suites/common/discover/group3/_request_counts.ts b/x-pack/test_serverless/functional/test_suites/common/discover/group3/_request_counts.ts index 6402b5ce4737c..43de4415dd257 100644 --- a/x-pack/test_serverless/functional/test_suites/common/discover/group3/_request_counts.ts +++ b/x-pack/test_serverless/functional/test_suites/common/discover/group3/_request_counts.ts @@ -127,11 +127,24 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - it('should send no more than 2 requests (documents + chart) when toggling the chart visibility', async () => { - await expectSearches(type, 2, async () => { + it(`should send no requests (documents + chart) when toggling the chart visibility`, async () => { + await expectSearches(type, 0, async () => { + // hide chart + await PageObjects.discover.toggleChartVisibility(); + // show chart await PageObjects.discover.toggleChartVisibility(); }); - await expectSearches(type, 2, async () => { + }); + it(`should send a request for chart data when toggling the chart visibility after a time range change`, async () => { + // hide chart + await PageObjects.discover.toggleChartVisibility(); + await PageObjects.timePicker.setAbsoluteRange( + 'Sep 21, 2015 @ 06:31:44.000', + 'Sep 24, 2015 @ 00:00:00.000' + ); + await waitForLoadingToFinish(); + await expectSearches(type, 1, async () => { + // show chart, we expect a request for the chart data, since the time range changed await PageObjects.discover.toggleChartVisibility(); }); }); diff --git a/x-pack/test_serverless/functional/test_suites/common/management/index_management/index_templates.ts b/x-pack/test_serverless/functional/test_suites/common/management/index_management/index_templates.ts index 5e2cfba50997f..29b480212cc71 100644 --- a/x-pack/test_serverless/functional/test_suites/common/management/index_management/index_templates.ts +++ b/x-pack/test_serverless/functional/test_suites/common/management/index_management/index_templates.ts @@ -86,16 +86,18 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { describe('Create index template', () => { const TEST_TEMPLATE_NAME = `test_template_${Date.now()}`; - afterEach(async () => { - await es.indices.deleteIndexTemplate({ name: TEST_TEMPLATE_NAME }, { ignore: [404] }); - }); - - it('Creates index template', async () => { + beforeEach(async () => { await testSubjects.click('createTemplateButton'); await testSubjects.setValue('nameField', TEST_TEMPLATE_NAME); await testSubjects.setValue('indexPatternsField', INDEX_PATTERN); + }); + + afterEach(async () => { + await es.indices.deleteIndexTemplate({ name: TEST_TEMPLATE_NAME }, { ignore: [404] }); + }); + it('Creates index template', async () => { // Click form summary step and then the submit button await testSubjects.click('formWizardStep-5'); await testSubjects.click('nextButton'); @@ -107,11 +109,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('can create an index template with logsdb index mode', async () => { - await testSubjects.click('createTemplateButton'); - // Fill out required fields - await testSubjects.setValue('nameField', TEST_TEMPLATE_NAME); - await testSubjects.setValue('indexPatternsField', INDEX_PATTERN); - await testSubjects.click('indexModeField'); await testSubjects.click('index_mode_logsdb'); @@ -129,5 +126,113 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.click('closeDetailsButton'); }); }); + + describe('Modify index template', () => { + const INDEX_TEMPLATE_NAME = 'index-template-test-name'; + + before(async () => { + await es.indices.putIndexTemplate({ + name: INDEX_TEMPLATE_NAME, + index_patterns: ['logsdb-test-index-pattern'], + data_stream: {}, + template: { + settings: { + mode: 'logsdb', + }, + }, + }); + + await testSubjects.click('reloadButton'); + }); + + after(async () => { + await es.indices.deleteIndexTemplate({ name: INDEX_TEMPLATE_NAME }, { ignore: [404] }); + }); + + it('can modify ignore_above, ignore_malformed, ignore_dynamic_beyond_limit, subobjects and timestamp format in an index template with logsdb index mode', async () => { + await pageObjects.indexManagement.clickIndexTemplateNameLink(INDEX_TEMPLATE_NAME); + await testSubjects.click('manageTemplateButton'); + await testSubjects.click('editIndexTemplateButton'); + await pageObjects.header.waitUntilLoadingHasFinished(); + + // Navigate to Index Settings + await testSubjects.click('formWizardStep-2'); + await pageObjects.header.waitUntilLoadingHasFinished(); + + // Modify Index settings + await testSubjects.setValue( + 'kibanaCodeEditor', + JSON.stringify({ + index: { + mapping: { + ignore_above: '20', + total_fields: { + ignore_dynamic_beyond_limit: 'true', + }, + ignore_malformed: 'true', + }, + }, + }), + { + clearWithKeyboard: true, + } + ); + + // Navigate to Mappings + await testSubjects.click('formWizardStep-3'); + await pageObjects.header.waitUntilLoadingHasFinished(); + const mappingTabs = await testSubjects.findAll('formTab'); + await mappingTabs[3].click(); + + // Modify timestamp format + await testSubjects.click('comboBoxClearButton'); + await testSubjects.setValue('comboBoxInput', 'basic_date'); + await testSubjects.pressEnter('comboBoxInput'); + + // Modify subobjects + await testSubjects.click('subobjectsToggle'); + + // Navigate to the last step of the wizard + await testSubjects.click('formWizardStep-5'); + await pageObjects.header.waitUntilLoadingHasFinished(); + + // Click Create template + await pageObjects.indexManagement.clickNextButton(); + await pageObjects.header.waitUntilLoadingHasFinished(); + + const flyoutTabs = await testSubjects.findAll('tab'); + + // Verify Index Settings + await flyoutTabs[1].click(); + await pageObjects.header.waitUntilLoadingHasFinished(); + expect(await testSubjects.exists('settingsTabContent')).to.be(true); + const settingsTabContent = await testSubjects.getVisibleText('settingsTabContent'); + expect(JSON.parse(settingsTabContent)).to.eql({ + index: { + mode: 'logsdb', + mapping: { + ignore_above: '20', + total_fields: { + ignore_dynamic_beyond_limit: 'true', + }, + ignore_malformed: 'true', + }, + }, + }); + + // Verify Mappings + await flyoutTabs[2].click(); + await pageObjects.header.waitUntilLoadingHasFinished(); + expect(await testSubjects.exists('mappingsTabContent')).to.be(true); + const mappingsTabContent = await testSubjects.getVisibleText('mappingsTabContent'); + expect(JSON.parse(mappingsTabContent)).to.eql({ + dynamic_date_formats: ['basic_date'], + subobjects: false, + }); + + // Close detail tab + await testSubjects.click('closeDetailsButton'); + }); + }); }); }; diff --git a/x-pack/test_serverless/functional/test_suites/observability/cases/view_case.ts b/x-pack/test_serverless/functional/test_suites/observability/cases/view_case.ts index f23b2d806ee0a..9556bfa552b80 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/cases/view_case.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/cases/view_case.ts @@ -36,7 +36,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { // https://github.com/elastic/kibana/pull/190690 // fails after missing `awaits` were added - describe.skip('Case View', function () { + describe('Case View', function () { before(async () => { await svlCommonPage.loginWithPrivilegedRole(); }); @@ -235,6 +235,8 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { await cases.common.selectSeverity(CaseSeverity.MEDIUM); + await header.waitUntilLoadingHasFinished(); + await cases.common.changeCaseStatusViaDropdownAndVerify(CaseStatuses['in-progress']); await header.waitUntilLoadingHasFinished(); @@ -272,7 +274,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { }); // FLAKY - describe.skip('Lens visualization', () => { + describe('Lens visualization', () => { before(async () => { await cases.testResources.installKibanaSampleData('logs'); await createAndNavigateToCase(getPageObject, getService, owner); diff --git a/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_summary.ts b/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_summary.ts index eb7f4aa5da310..ac4a2597f3d95 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_summary.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_summary.ts @@ -48,8 +48,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ]); }; - // Failing: See https://github.com/elastic/kibana/issues/205545 - describe.skip('Dataset quality summary', () => { + describe('Dataset quality summary', () => { before(async () => { await synthtrace.index(getInitialTestLogs({ to, count: 4 })); await PageObjects.svlCommonPage.loginAsViewer(); diff --git a/x-pack/test_serverless/functional/test_suites/observability/ml/index.ts b/x-pack/test_serverless/functional/test_suites/observability/ml/index.ts index ba88fce593abf..6a9b475f479b5 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/ml/index.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/ml/index.ts @@ -14,5 +14,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { this.tags(['failsOnMKI']); loadTestFile(require.resolve('./anomaly_detection_jobs_list')); loadTestFile(require.resolve('./search_bar_features')); + loadTestFile(require.resolve('./memory_usage')); + loadTestFile(require.resolve('./notifications')); }); } diff --git a/x-pack/test_serverless/functional/test_suites/observability/ml/memory_usage.ts b/x-pack/test_serverless/functional/test_suites/observability/ml/memory_usage.ts new file mode 100644 index 0000000000000..98906601f3a14 --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/observability/ml/memory_usage.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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const ml = getService('ml'); + const svlMl = getService('svlMl'); + const PageObjects = getPageObjects(['svlCommonPage']); + + const availableMLObjectTypes = ['Anomaly detection jobs', 'Trained models']; + + describe('Memory usage page', function () { + before(async () => { + await PageObjects.svlCommonPage.loginWithPrivilegedRole(); + }); + + it('opens page with all available ML object types for Observability', async () => { + await ml.navigation.navigateToMl(); + await svlMl.navigation.observability.navigateToMemoryUsage(); + + await ml.memoryUsage.assertJobTreeComboBoxExists(); + + const selectedItems = await ml.memoryUsage.getSelectedChartItems(); + expect(selectedItems).to.eql(availableMLObjectTypes); + + // Make sure there are no other available indicies + const options = await ml.memoryUsage.getJobTreeComboBoxOptions(); + expect(options).empty(); + }); + }); +} diff --git a/x-pack/test_serverless/functional/test_suites/observability/ml/notifications.ts b/x-pack/test_serverless/functional/test_suites/observability/ml/notifications.ts new file mode 100644 index 0000000000000..c4119bec904aa --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/observability/ml/notifications.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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const ml = getService('ml'); + const svlMl = getService('svlMl'); + const PageObjects = getPageObjects(['svlCommonPage']); + + const expectedObservabilityTypeFilters = ['Anomaly Detection', 'Inference', 'System']; + + describe('Notifications page', function () { + before(async () => { + await PageObjects.svlCommonPage.loginWithPrivilegedRole(); + }); + + it('displays only notification types for observability projects', async () => { + await svlMl.navigation.observability.navigateToNotifications(); + const availableTypeFilters = await ml.notifications.getAvailableTypeFilters(); + + expect(availableTypeFilters).to.eql(expectedObservabilityTypeFilters); + }); + }); +} diff --git a/x-pack/test_serverless/functional/test_suites/search/search_index_detail.ts b/x-pack/test_serverless/functional/test_suites/search/search_index_detail.ts index 0dda7789b6f93..59621ca8512a0 100644 --- a/x-pack/test_serverless/functional/test_suites/search/search_index_detail.ts +++ b/x-pack/test_serverless/functional/test_suites/search/search_index_detail.ts @@ -70,17 +70,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('should have basic example texts', async () => { await pageObjects.svlSearchIndexDetailPage.expectHasSampleDocuments(); }); - - it('should have other example texts when mapping changed', async () => { - await es.indices.putMapping({ - index: indexNameCodeExample, - properties: { - text: { type: 'text' }, - number: { type: 'integer' }, - }, - }); - await pageObjects.svlSearchIndexDetailPage.expectSampleDocumentsWithCustomMappings(); - }); }); describe('API key details', () => { diff --git a/x-pack/test_serverless/functional/test_suites/security/ftr/cases/view_case.ts b/x-pack/test_serverless/functional/test_suites/security/ftr/cases/view_case.ts index eaec4fd9dbaa7..3620ff41281ff 100644 --- a/x-pack/test_serverless/functional/test_suites/security/ftr/cases/view_case.ts +++ b/x-pack/test_serverless/functional/test_suites/security/ftr/cases/view_case.ts @@ -37,7 +37,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { // https://github.com/elastic/kibana/pull/190690 // fails after missing `awaits` were added - describe.skip('Case View', function () { + describe('Case View', function () { before(async () => { await svlCommonPage.loginWithPrivilegedRole(); }); @@ -235,6 +235,8 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { await cases.common.selectSeverity(CaseSeverity.MEDIUM); + await header.waitUntilLoadingHasFinished(); + await cases.common.changeCaseStatusViaDropdownAndVerify(CaseStatuses['in-progress']); await header.waitUntilLoadingHasFinished(); @@ -272,7 +274,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { }); // FLAKY - describe.skip('Lens visualization', () => { + describe('Lens visualization', () => { before(async () => { await cases.testResources.installKibanaSampleData('logs'); await createAndNavigateToCase(getPageObject, getService, owner); diff --git a/x-pack/test_serverless/functional/test_suites/security/ml/index.ts b/x-pack/test_serverless/functional/test_suites/security/ml/index.ts index 5b486161646df..ef2108b99f4eb 100644 --- a/x-pack/test_serverless/functional/test_suites/security/ml/index.ts +++ b/x-pack/test_serverless/functional/test_suites/security/ml/index.ts @@ -13,5 +13,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./data_frame_analytics_jobs_list')); loadTestFile(require.resolve('./trained_models_list')); loadTestFile(require.resolve('./search_bar_features')); + loadTestFile(require.resolve('./memory_usage')); + loadTestFile(require.resolve('./notifications')); }); } diff --git a/x-pack/test_serverless/functional/test_suites/security/ml/memory_usage.ts b/x-pack/test_serverless/functional/test_suites/security/ml/memory_usage.ts new file mode 100644 index 0000000000000..15be625d0510f --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/security/ml/memory_usage.ts @@ -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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const ml = getService('ml'); + const svlMl = getService('svlMl'); + const PageObjects = getPageObjects(['svlCommonPage']); + + const availableMLObjectTypes = [ + 'Anomaly detection jobs', + 'Data frame analytics jobs', + 'Trained models', + ]; + + describe('Memory usage page', function () { + before(async () => { + await PageObjects.svlCommonPage.loginWithPrivilegedRole(); + }); + + it('opens page with all available ML object types for Security', async () => { + await ml.navigation.navigateToMl(); + await svlMl.navigation.security.navigateToMemoryUsage(); + + await ml.memoryUsage.assertJobTreeComboBoxExists(); + + const selectedItems = await ml.memoryUsage.getSelectedChartItems(); + expect(selectedItems).to.eql(availableMLObjectTypes); + + // Make sure there are no other available indicies + const options = await ml.memoryUsage.getJobTreeComboBoxOptions(); + expect(options).empty(); + }); + }); +} diff --git a/x-pack/test_serverless/functional/test_suites/security/ml/notifications.ts b/x-pack/test_serverless/functional/test_suites/security/ml/notifications.ts new file mode 100644 index 0000000000000..7d8ecec984957 --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/security/ml/notifications.ts @@ -0,0 +1,35 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const ml = getService('ml'); + const svlMl = getService('svlMl'); + const PageObjects = getPageObjects(['svlCommonPage']); + + const expectedSecurityTypeFilters = [ + 'Anomaly Detection', + 'Data Frame Analytics', + 'Inference', + 'System', + ]; + + describe('Notifications page', function () { + before(async () => { + await PageObjects.svlCommonPage.loginWithPrivilegedRole(); + }); + + it('displays only notification types for security projects', async () => { + await svlMl.navigation.security.navigateToNotifications(); + const availableTypeFilters = await ml.notifications.getAvailableTypeFilters(); + + expect(availableTypeFilters).to.eql(expectedSecurityTypeFilters); + }); + }); +} diff --git a/x-pack/test_serverless/shared/lib/security/kibana_roles/project_controller_security_roles.yml b/x-pack/test_serverless/shared/lib/security/kibana_roles/project_controller_security_roles.yml index 8da8650a75fa3..86c9d1acb57b0 100644 --- a/x-pack/test_serverless/shared/lib/security/kibana_roles/project_controller_security_roles.yml +++ b/x-pack/test_serverless/shared/lib/security/kibana_roles/project_controller_security_roles.yml @@ -6,19 +6,19 @@ viewer: cluster: [] indices: - names: - - ".siem-signals*" - - ".lists-*" - - ".items-*" + - '.siem-signals*' + - '.lists-*' + - '.items-*' privileges: - - "read" - - "view_index_metadata" + - 'read' + - 'view_index_metadata' allow_restricted_indices: false - names: - - ".alerts*" - - ".preview.alerts*" + - '.alerts*' + - '.preview.alerts*' privileges: - - "read" - - "view_index_metadata" + - 'read' + - 'view_index_metadata' allow_restricted_indices: false - names: - apm-*-transaction* @@ -30,24 +30,26 @@ viewer: - packetbeat-* - winlogbeat-* - metrics-endpoint.metadata_current_* - - ".fleet-agents*" - - ".fleet-actions*" - - "risk-score.risk-score-*" - - ".asset-criticality.asset-criticality-*" - - ".entities.v1.latest.security_*" - - ".ml-anomalies-*" + - '.fleet-agents*' + - '.fleet-actions*' + - 'risk-score.risk-score-*' + - '.asset-criticality.asset-criticality-*' + - '.entities.v1.latest.security_*' + - '.ml-anomalies-*' privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.read - - feature_siem.read_alerts - - feature_siem.endpoint_list_read + - feature_siemV2.read + - feature_siemV2.read_alerts + - feature_siemV2.endpoint_list_read - feature_securitySolutionCases.read - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.read + - feature_securitySolutionNotes.read - feature_actions.read - feature_builtInAlerts.read - feature_osquery.read @@ -57,7 +59,7 @@ viewer: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' run_as: [] # modeled after t3_analyst @@ -65,14 +67,14 @@ editor: cluster: [] indices: - names: - - ".siem-signals*" - - ".lists-*" - - ".items-*" + - '.siem-signals*' + - '.lists-*' + - '.items-*' privileges: - - "read" - - "view_index_metadata" - - "write" - - "maintenance" + - 'read' + - 'view_index_metadata' + - 'write' + - 'maintenance' allow_restricted_indices: false - names: - apm-*-transaction* @@ -87,47 +89,49 @@ editor: - read - write - names: - - ".internal.alerts*" - - ".alerts*" - - ".internal.preview.alerts*" - - ".preview.alerts*" - - "risk-score.risk-score-*" + - '.internal.alerts*' + - '.alerts*' + - '.internal.preview.alerts*' + - '.preview.alerts*' + - 'risk-score.risk-score-*' privileges: - - "read" - - "view_index_metadata" - - "write" - - "maintenance" + - 'read' + - 'view_index_metadata' + - 'write' + - 'maintenance' - names: - - ".asset-criticality.asset-criticality-*" - - ".entities.v1.latest.security_*" + - '.asset-criticality.asset-criticality-*' + - '.entities.v1.latest.security_*' privileges: - - "read" - - "write" + - 'read' + - 'write' allow_restricted_indices: false - names: - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all - - feature_siem.policy_management_read # Elastic Defend Policy Management - - feature_siem.host_isolation_all - - feature_siem.process_operations_all - - feature_siem.actions_log_management_all # Response actions history - - feature_siem.file_operations_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all + - feature_siemV2.policy_management_read # Elastic Defend Policy Management + - feature_siemV2.host_isolation_all + - feature_siemV2.process_operations_all + - feature_siemV2.actions_log_management_all # Response actions history + - feature_siemV2.file_operations_all - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.read - feature_builtInAlerts.all - feature_osquery.all @@ -137,15 +141,15 @@ editor: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' run_as: [] t1_analyst: cluster: indices: - names: - - ".alerts-security*" - - ".siem-signals-*" + - '.alerts-security*' + - '.siem-signals-*' privileges: - read - write @@ -162,24 +166,26 @@ t1_analyst: - packetbeat-* - winlogbeat-* - metrics-endpoint.metadata_current_* - - ".fleet-agents*" - - ".fleet-actions*" + - '.fleet-agents*' + - '.fleet-actions*' - risk-score.risk-score-* - .asset-criticality.asset-criticality-* - .entities.v1.latest.security_* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.read - - feature_siem.read_alerts - - feature_siem.endpoint_list_read + - feature_siemV2.read + - feature_siemV2.read_alerts + - feature_siemV2.endpoint_list_read - feature_securitySolutionCases.read - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.read + - feature_securitySolutionNotes.read - feature_actions.read - feature_builtInAlerts.read - feature_osquery.read @@ -190,7 +196,7 @@ t1_analyst: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' t2_analyst: cluster: @@ -218,7 +224,7 @@ t2_analyst: - .fleet-actions* - risk-score.risk-score-* - .entities.v1.latest.security_* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read - names: @@ -227,15 +233,17 @@ t2_analyst: - read - write applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.read - - feature_siem.read_alerts - - feature_siem.endpoint_list_read + - feature_siemV2.read + - feature_siemV2.read_alerts + - feature_siemV2.endpoint_list_read - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.read + - feature_securitySolutionNotes.read - feature_actions.read - feature_builtInAlerts.read - feature_osquery.read @@ -246,7 +254,7 @@ t2_analyst: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' t3_analyst: cluster: @@ -284,31 +292,33 @@ t3_analyst: - .fleet-actions* - risk-score.risk-score-* - .entities.v1.latest.security_* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all - - feature_siem.policy_management_read # Elastic Defend Policy Management - - feature_siem.host_isolation_all - - feature_siem.process_operations_all - - feature_siem.actions_log_management_all # Response actions history - - feature_siem.file_operations_all - - feature_siem.scan_operations_all - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all + - feature_siemV2.policy_management_read # Elastic Defend Policy Management + - feature_siemV2.host_isolation_all + - feature_siemV2.process_operations_all + - feature_siemV2.actions_log_management_all # Response actions history + - feature_siemV2.file_operations_all + - feature_siemV2.scan_operations_all + - feature_siemV2.workflow_insights_all - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.read - feature_builtInAlerts.all - feature_osquery.all @@ -318,7 +328,7 @@ t3_analyst: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' threat_intelligence_analyst: cluster: @@ -354,19 +364,21 @@ threat_intelligence_analyst: - .fleet-actions* - risk-score.risk-score-* - .entities.v1.latest.security_* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.all - - feature_siem.endpoint_list_read - - feature_siem.blocklist_all + - feature_siemV2.all + - feature_siemV2.endpoint_list_read + - feature_siemV2.blocklist_all - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.read - feature_builtInAlerts.read - feature_osquery.all @@ -376,7 +388,7 @@ threat_intelligence_analyst: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' rule_author: cluster: @@ -417,27 +429,29 @@ rule_author: - .fleet-actions* - risk-score.risk-score-* - .entities.v1.latest.security_* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.policy_management_all - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_read - - feature_siem.blocklist_all # Elastic Defend Policy Management - - feature_siem.actions_log_management_read - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.policy_management_all + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_read + - feature_siemV2.blocklist_all # Elastic Defend Policy Management + - feature_siemV2.actions_log_management_read + - feature_siemV2.workflow_insights_all - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.read - feature_builtInAlerts.all - feature_osquery.all @@ -447,7 +461,7 @@ rule_author: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' soc_manager: cluster: @@ -488,34 +502,36 @@ soc_manager: - .fleet-actions* - risk-score.risk-score-* - .asset-criticality.asset-criticality-* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - feature_generalCases.all - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.policy_management_all - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all - - feature_siem.host_isolation_all - - feature_siem.process_operations_all - - feature_siem.actions_log_management_all - - feature_siem.file_operations_all - - feature_siem.execute_operations_all - - feature_siem.scan_operations_all - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.policy_management_all + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all + - feature_siemV2.host_isolation_all + - feature_siemV2.process_operations_all + - feature_siemV2.actions_log_management_all + - feature_siemV2.file_operations_all + - feature_siemV2.execute_operations_all + - feature_siemV2.scan_operations_all + - feature_siemV2.workflow_insights_all - feature_securitySolutionCases.all - feature_observabilityCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all @@ -526,10 +542,10 @@ soc_manager: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' detections_admin: - cluster: ["manage_index_templates", "manage_transform"] + cluster: ['manage_index_templates', 'manage_transform'] indices: - names: - apm-*-transaction* @@ -554,7 +570,7 @@ detections_admin: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read - names: @@ -568,15 +584,17 @@ detections_admin: - read - write applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.all - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.all - feature_builtInAlerts.all - feature_dev_tools.all @@ -586,7 +604,7 @@ detections_admin: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' platform_engineer: cluster: @@ -617,27 +635,29 @@ platform_engineer: - read - write - names: - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.all - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.policy_management_all - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all # Elastic Defend Policy Management - - feature_siem.actions_log_management_read - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.policy_management_all + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all # Elastic Defend Policy Management + - feature_siemV2.actions_log_management_read + - feature_siemV2.workflow_insights_all - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.all - feature_builtInAlerts.all - feature_fleet.all @@ -650,7 +670,7 @@ platform_engineer: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' endpoint_operations_analyst: cluster: @@ -674,7 +694,7 @@ endpoint_operations_analyst: - .items* - risk-score.risk-score-* - .entities.v1.latest.security_* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read - names: @@ -692,27 +712,29 @@ endpoint_operations_analyst: - read - write applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.policy_management_all - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all - - feature_siem.host_isolation_all - - feature_siem.process_operations_all - - feature_siem.actions_log_management_all # Response History - - feature_siem.file_operations_all - - feature_siem.execute_operations_all # Execute - - feature_siem.scan_operations_all - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.policy_management_all + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all + - feature_siemV2.host_isolation_all + - feature_siemV2.process_operations_all + - feature_siemV2.actions_log_management_all # Response History + - feature_siemV2.file_operations_all + - feature_siemV2.execute_operations_all # Execute + - feature_siemV2.scan_operations_all + - feature_siemV2.workflow_insights_all - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all @@ -724,7 +746,7 @@ endpoint_operations_analyst: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' endpoint_policy_manager: cluster: @@ -746,7 +768,7 @@ endpoint_policy_manager: - winlogbeat-* - risk-score.risk-score-* - .entities.v1.latest.security_* - - ".ml-anomalies-*" + - '.ml-anomalies-*' privileges: - read - names: @@ -766,22 +788,24 @@ endpoint_policy_manager: - write - manage applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.all - - feature_siem.all - - feature_siem.read_alerts - - feature_siem.crud_alerts - - feature_siem.policy_management_all - - feature_siem.endpoint_list_all - - feature_siem.trusted_applications_all - - feature_siem.event_filters_all - - feature_siem.host_isolation_exceptions_all - - feature_siem.blocklist_all # Elastic Defend Policy Management - - feature_siem.workflow_insights_all + - feature_siemV2.all + - feature_siemV2.read_alerts + - feature_siemV2.crud_alerts + - feature_siemV2.policy_management_all + - feature_siemV2.endpoint_list_all + - feature_siemV2.trusted_applications_all + - feature_siemV2.event_filters_all + - feature_siemV2.host_isolation_exceptions_all + - feature_siemV2.blocklist_all # Elastic Defend Policy Management + - feature_siemV2.workflow_insights_all - feature_securitySolutionCases.all - feature_securitySolutionAssistant.all - feature_securitySolutionAttackDiscovery.all + - feature_securitySolutionTimeline.all + - feature_securitySolutionNotes.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all @@ -793,4 +817,4 @@ endpoint_policy_manager: - feature_graph.all - feature_maps.all - feature_visualize.all - resources: "*" + resources: '*' diff --git a/yarn.lock b/yarn.lock index dcbb1fa2a357f..5b6a37abe6ac5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -711,7 +711,7 @@ "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.3" chokidar "^3.4.0" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.24.7", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.24.7", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== @@ -3483,11 +3483,6 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/momoa@^2.0.3": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@humanwhocodes/momoa/-/momoa-2.0.4.tgz#8b9e7a629651d15009c3587d07a222deeb829385" - integrity sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA== - "@humanwhocodes/object-schema@^2.0.2": version "2.0.3" resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" @@ -9212,24 +9207,6 @@ unbzip2-stream "^1.4.3" yargs "^17.7.2" -"@readme/better-ajv-errors@^1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@readme/better-ajv-errors/-/better-ajv-errors-1.6.0.tgz#cf96740bd71d256ed628f3a7466ecae0846edd62" - integrity sha512-9gO9rld84Jgu13kcbKRU+WHseNhaVt76wYMeRDGsUGYxwJtI3RmEJ9LY9dZCYQGI8eUZLuxb5qDja0nqklpFjQ== - dependencies: - "@babel/code-frame" "^7.16.0" - "@babel/runtime" "^7.21.0" - "@humanwhocodes/momoa" "^2.0.3" - chalk "^4.1.2" - json-to-ast "^2.0.3" - jsonpointer "^5.0.0" - leven "^3.1.0" - -"@readme/http-status-codes@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@readme/http-status-codes/-/http-status-codes-7.2.0.tgz#805d281346eb4c25d987d8b86e23b4dba116a96f" - integrity sha512-/dBh9qw3QhJYqlGwt2I+KUP/lQ6nytdCx3aq+GpMUhibLHF3O7fwoowNcTwlbnwtyJ+TJYTIIrp3oVUlRNx3fA== - "@readme/json-schema-ref-parser@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@readme/json-schema-ref-parser/-/json-schema-ref-parser-1.2.0.tgz#8552cde8f8ecf455398c59aa6e2cf5ed2d0f3d31" @@ -9240,37 +9217,6 @@ call-me-maybe "^1.0.1" js-yaml "^4.1.0" -"@readme/openapi-parser@^2.6.0": - version "2.6.0" - resolved "https://registry.yarnpkg.com/@readme/openapi-parser/-/openapi-parser-2.6.0.tgz#fcd17459270e209dad5e0b0654b2ba74d64104c8" - integrity sha512-pyFJXezWj9WI1O+gdp95CoxfY+i+Uq3kKk4zXIFuRAZi9YnHpHOpjumWWr67wkmRTw19Hskh9spyY0Iyikf3fA== - dependencies: - "@apidevtools/swagger-methods" "^3.0.2" - "@jsdevtools/ono" "^7.1.3" - "@readme/better-ajv-errors" "^1.6.0" - "@readme/json-schema-ref-parser" "^1.2.0" - "@readme/openapi-schemas" "^3.1.0" - ajv "^8.12.0" - ajv-draft-04 "^1.0.0" - call-me-maybe "^1.0.1" - -"@readme/openapi-schemas@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@readme/openapi-schemas/-/openapi-schemas-3.1.0.tgz#5ff4b704af6a8b108f9d577fd87cf73e9e7b3178" - integrity sha512-9FC/6ho8uFa8fV50+FPy/ngWN53jaUu4GRXlAjcxIRrzhltJnpKkBG2Tp0IDraFJeWrOpk84RJ9EMEEYzaI1Bw== - -"@readme/postman-to-openapi@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@readme/postman-to-openapi/-/postman-to-openapi-4.1.0.tgz#ba40dd4374f74cf2112e23e031320ba2c3e0da44" - integrity sha512-VvV2Hzjskz01m8doSn7Ypt6cSZzgjnypVqXy1ipThbyYD6SGiM74VSePXykOODj/43Y2m6zeYedPk/ZLts/HvQ== - dependencies: - "@readme/http-status-codes" "^7.2.0" - js-yaml "^4.1.0" - jsonc-parser "3.2.0" - lodash.camelcase "^4.3.0" - marked "^4.3.0" - mustache "^4.2.0" - "@redocly/ajv@^8.11.2": version "8.11.2" resolved "https://registry.yarnpkg.com/@redocly/ajv/-/ajv-8.11.2.tgz#46e1bf321ec0ac1e0fd31dea41a3d1fcbdcda0b5" @@ -11446,11 +11392,6 @@ resolved "https://registry.yarnpkg.com/@types/cssstyle/-/cssstyle-2.2.4.tgz#3d333ab9f8e6c40183ad1d6ebeebfcb8da2bfe4b" integrity sha512-FTGMeuHZtLB7hRm+NGvOLZElslR1UkKvZmEmFevOZe/e7Av0nFleka1s8ZwoX+QvbJ2y7r9NDZXIzyqpRWDJXQ== -"@types/cytoscape@^3.21.8": - version "3.21.8" - resolved "https://registry.yarnpkg.com/@types/cytoscape/-/cytoscape-3.21.8.tgz#6166a2eabd66d3ae3259024875e037492adb8db6" - integrity sha512-6Bo9ZDrv0vfwe8Sg/ERc5VL0yU0gYvP4dgZi0fAXYkKHfyHaNqWRMcwYm3mu4sLsXbB8ZuXE75sR7qnaOL5JgQ== - "@types/d3-array@^2.12.1": version "2.12.3" resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-2.12.3.tgz#8d16d51fb04ad5a5a8ebe14eb8263a579f1efdd1" @@ -11950,10 +11891,10 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.0.tgz#d774355e41f372d5350a4d0714abb48194a489c3" integrity sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA== -"@types/lodash@^4.17.0", "@types/lodash@^4.17.13": - version "4.17.13" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.13.tgz#786e2d67cfd95e32862143abe7463a7f90c300eb" - integrity sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg== +"@types/lodash@^4.17.0", "@types/lodash@^4.17.14": + version "4.17.14" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.14.tgz#bafc053533f4cdc5fcc9635af46a963c1f3deaff" + integrity sha512-jsxagdikDiDBeIRaPYtArcT8my4tN1og7MtMRquFT3XNA6axxyHDRUemqDz/taRDdOUn0GnGHRCuff4q48sW9A== "@types/long@^4.0.1": version "4.0.2" @@ -12146,12 +12087,10 @@ resolved "https://registry.yarnpkg.com/@types/nunjucks/-/nunjucks-3.2.6.tgz#6d6e0363719545df8b9a024279902edf68b2caa9" integrity sha512-pHiGtf83na1nCzliuAdq8GowYiXvH5l931xZ0YEHaLMNFgynpEqx+IPStlu7UaDkehfvl01e4x/9Tpwhy7Ue3w== -"@types/object-hash@^1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@types/object-hash/-/object-hash-1.3.0.tgz#b20db2074129f71829d61ff404e618c4ac3d73cf" - integrity sha512-il4NIe4jTx4lfhkKaksmmGHw5EsVkO8sHWkpJHM9m59r1dtsVadLSrJqdE8zU74NENDAsR3oLIOlooRAXlPLNA== - dependencies: - "@types/node" "*" +"@types/object-hash@^3.0.6": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/object-hash/-/object-hash-3.0.6.tgz#25c052428199d374ef723b7b0ed44b5bfe1b3029" + integrity sha512-fOBV8C1FIu2ELinoILQ+ApxcUKz4ngq+IWUYrxSGjXzzjUALijilampwkMgEtJ+h2njAW3pi853QpzNVCHB73w== "@types/ora@^1.3.5": version "1.3.5" @@ -12623,11 +12562,6 @@ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-10.0.0.tgz#e9c07fe50da0f53dc24970cca94d619ff03f6f6d" integrity sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ== -"@types/uuid@^9.0.0": - version "9.0.0" - resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.0.tgz#53ef263e5239728b56096b0a869595135b7952d2" - integrity sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q== - "@types/uuid@^9.0.1": version "9.0.8" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba" @@ -13325,7 +13259,7 @@ acorn@^7.0.0, acorn@^7.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.0.4, acorn@^8.1.0, acorn@^8.11.0, acorn@^8.12.1, acorn@^8.14.0, acorn@^8.4.1, acorn@^8.8.0, acorn@^8.8.2, acorn@^8.9.0: +acorn@^8.0.4, acorn@^8.1.0, acorn@^8.11.0, acorn@^8.14.0, acorn@^8.4.1, acorn@^8.8.0, acorn@^8.8.2, acorn@^8.9.0: version "8.14.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== @@ -13458,7 +13392,7 @@ ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.0.1, ajv@^8.12.0, ajv@^8.17.1, ajv@^8.8.0: +ajv@^8.0.0, ajv@^8.0.1, ajv@^8.17.1, ajv@^8.8.0: version "8.17.1" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== @@ -15608,11 +15542,6 @@ code-block-writer@^11.0.0: dependencies: tslib "2.3.1" -code-error-fragment@0.0.230: - version "0.0.230" - resolved "https://registry.yarnpkg.com/code-error-fragment/-/code-error-fragment-0.0.230.tgz#d736d75c832445342eca1d1fedbf17d9618b14d7" - integrity sha512-cadkfKp6932H8UkhzE/gcUqhRMNf8jHzkAN7+5Myabswaghu4xABTgPHDCjW+dBAJxj/SpkTYokpzDqY4pCzQw== - code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -15784,6 +15713,11 @@ commander@^12.1.0: resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== +commander@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-13.0.0.tgz#1b161f60ee3ceb8074583a0f95359a4f8701845c" + integrity sha512-oPYleIY8wmTVzkvQq10AEok6YcTC4sRUBl8F9gVuwchGVUCTbl/vhLTaQqutuuySYOsu8YTgV+OxKc/8Yvx+mQ== + commander@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" @@ -16568,10 +16502,10 @@ cytoscape-dagre@^2.5.0: dependencies: dagre "^0.8.5" -cytoscape@^3.30.4: - version "3.30.4" - resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.30.4.tgz#3404da0a159c00a1a3df2c85b2b43fdc66a0e28e" - integrity sha512-OxtlZwQl1WbwMmLiyPSEBuzeTIQnwZhJYYWFzZ2PhEHVFwpeaqNIkUzSiso00D98qk60l8Gwon2RP304d3BJ1A== +cytoscape@^3.31.0: + version "3.31.0" + resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.31.0.tgz#cffbbb8ca51db01cbf360e0cf59088db6d429837" + integrity sha512-zDGn1K/tfZwEnoGOcHc0H4XazqAAXAuDpcYw9mUnUjATjqljyCNGJv8uEvbvxGaGHaVshxMecyl6oc6uKzRfbw== "d3-array@1 - 3", "d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3.2.2, d3-array@^3.2.2: version "3.2.2" @@ -17247,33 +17181,33 @@ dependency-check@^4.1.0: read-package-json "^2.0.10" resolve "^1.1.7" -dependency-cruiser@^16.4.2: - version "16.4.2" - resolved "https://registry.yarnpkg.com/dependency-cruiser/-/dependency-cruiser-16.4.2.tgz#586487e1ac355912a0ad2310b830b63054733e01" - integrity sha512-mQZM95WwIvKzYYdj+1RgIBuJ6qbr1cfyzTt62dDJVrWAShfhV9IEkG/Xv4S2iD5sT+Gt3oFWyZjwNufAhcbtWA== +dependency-cruiser@^16.8.0: + version "16.9.0" + resolved "https://registry.yarnpkg.com/dependency-cruiser/-/dependency-cruiser-16.9.0.tgz#3273881daa3613fe8a00639f26a044ec6004afa0" + integrity sha512-Gc/xHNOBq1nk5i7FPCuexCD0m2OXB/WEfiSHfNYQaQaHZiZltnl5Ixp/ZG38Jvi8aEhKBQTHV4Aw6gmR7rWlOw== dependencies: - acorn "^8.12.1" + acorn "^8.14.0" acorn-jsx "^5.3.2" acorn-jsx-walk "^2.0.0" acorn-loose "^8.4.0" acorn-walk "^8.3.4" ajv "^8.17.1" - commander "^12.1.0" - enhanced-resolve "^5.17.1" - ignore "^6.0.2" + commander "^13.0.0" + enhanced-resolve "^5.18.0" + ignore "^7.0.0" interpret "^3.1.1" is-installed-globally "^1.0.0" json5 "^2.2.3" memoize "^10.0.0" - picocolors "^1.1.0" + picocolors "^1.1.1" picomatch "^4.0.2" prompts "^2.4.2" rechoir "^0.8.0" safe-regex "^2.1.1" semver "^7.6.3" teamcity-service-messages "^0.1.14" - tsconfig-paths-webpack-plugin "^4.1.0" - watskeburt "^4.1.0" + tsconfig-paths-webpack-plugin "^4.2.0" + watskeburt "^4.2.2" dependency-tree@^10.0.9: version "10.0.9" @@ -17918,10 +17852,10 @@ enhanced-resolve@^4.5.0: memory-fs "^0.5.0" tapable "^1.0.0" -enhanced-resolve@^5.14.1, enhanced-resolve@^5.17.1, enhanced-resolve@^5.7.0: - version "5.17.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" - integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== +enhanced-resolve@^5.14.1, enhanced-resolve@^5.17.1, enhanced-resolve@^5.18.0, enhanced-resolve@^5.7.0: + version "5.18.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz#91eb1db193896b9801251eeff1c6980278b1e404" + integrity sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -20267,11 +20201,6 @@ graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -grapheme-splitter@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" - integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== - graphemer@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" @@ -21078,10 +21007,10 @@ ignore@^5.0.5, ignore@^5.1.1, ignore@^5.2.0, ignore@^5.2.1, ignore@^5.3.0: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== -ignore@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-6.0.2.tgz#77cccb72a55796af1b6d2f9eb14fa326d24f4283" - integrity sha512-InwqeHHN2XpumIkMvpl/DCJVrAHgCsG5+cn1XlnLWGwtZBm8QJfSusItfrwx81CTp5agNZqpKU2J/ccC5nGT4A== +ignore@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.0.tgz#52da780b009bd0845d1f9dd4d8ae6a7569ae73c4" + integrity sha512-lcX8PNQygAa22u/0BysEY8VhaFRzlOkvdlKczDPnJvrkJD1EuqzEky5VYYKM2iySIuaVIDv9N190DfSreSLw2A== immediate@~3.0.5: version "3.0.6" @@ -22924,14 +22853,6 @@ json-text-sequence@~0.3.0: dependencies: "@sovpro/delimited-stream" "^1.1.0" -json-to-ast@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/json-to-ast/-/json-to-ast-2.1.0.tgz#041a9fcd03c0845036acb670d29f425cea4faaf9" - integrity sha512-W9Lq347r8tA1DfMvAGn9QNcgYm4Wm7Yc+k8e6vezpMnRT+NHbtlxgNBXRVjXe9YM6eTn6+p/MKOlV/aABJcSnQ== - dependencies: - code-error-fragment "0.0.230" - grapheme-splitter "^1.0.4" - json5@*, json5@^2.1.2, json5@^2.2.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" @@ -22944,7 +22865,7 @@ json5@^1.0.1, json5@^1.0.2: dependencies: minimist "^1.2.0" -jsonc-parser@3.2.0, jsonc-parser@^3.0.0: +jsonc-parser@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== @@ -25430,17 +25351,6 @@ oas-linter@^3.2.2: should "^13.2.1" yaml "^1.10.0" -oas-normalize@^11.1.4: - version "11.1.4" - resolved "https://registry.yarnpkg.com/oas-normalize/-/oas-normalize-11.1.4.tgz#8d3e014b2e6ac6ef261b88e6513a5f012851aec7" - integrity sha512-K533PwDAvm3KtugGu4H/GtHrIrEbFRoLkT8fLY6PU+m80JxzhbVKG8eUJUHwr3NesTt8VSA6O2r6eBcdqkRe2A== - dependencies: - "@readme/openapi-parser" "^2.6.0" - "@readme/postman-to-openapi" "^4.1.0" - js-yaml "^4.1.0" - openapi-types "^12.1.3" - swagger2openapi "^7.0.8" - oas-resolver@^2.5.6: version "2.5.6" resolved "https://registry.yarnpkg.com/oas-resolver/-/oas-resolver-2.5.6.tgz#10430569cb7daca56115c915e611ebc5515c561b" @@ -25471,10 +25381,10 @@ oas-validator@^5.0.8: should "^13.2.1" yaml "^1.10.0" -oas@^25.2.0: - version "25.2.0" - resolved "https://registry.yarnpkg.com/oas/-/oas-25.2.0.tgz#0e933c213d2b3e54ca5a8576699ee052dd1dc306" - integrity sha512-u5PUUpWVPlAzqOFyMJKowvyMXupFMIMUjaqnNv4MkERvWGL91jgkO82teQqMrvUvNJNJxAkEjTyvcciZkGS9ag== +oas@^25.2.1: + version "25.2.1" + resolved "https://registry.yarnpkg.com/oas/-/oas-25.2.1.tgz#2cf0ac042e5ba7af0bfc2a9acea6d33699cd6b90" + integrity sha512-56NO/ThEzIQeniJHm12tFIIGaugcdZTxYWiWP0KV8W9DcdWRvk9tvBEKITFp9r62w7W25vobedpiApa9u/Aoxg== dependencies: "@readme/json-schema-ref-parser" "^1.2.0" "@types/json-schema" "^7.0.11" @@ -25482,7 +25392,6 @@ oas@^25.2.0: jsonpath-plus "^10.0.0" jsonpointer "^5.0.0" memoizee "^0.4.16" - oas-normalize "^11.1.4" openapi-types "^12.1.1" path-to-regexp "^8.1.0" remove-undefined-objects "^5.0.0" @@ -25506,11 +25415,16 @@ object-filter-sequence@^1.0.0: resolved "https://registry.yarnpkg.com/object-filter-sequence/-/object-filter-sequence-1.0.0.tgz#10bb05402fff100082b80d7e83991b10db411692" integrity sha512-CsubGNxhIEChNY4cXYuA6KXafztzHqzLLZ/y3Kasf3A+sa3lL9thq3z+7o0pZqzEinjXT6lXDPAfVWI59dUyzQ== -object-hash@^1.3.0, object-hash@^1.3.1: +object-hash@^1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df" integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA== +object-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" + integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== + object-identity-map@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/object-identity-map/-/object-identity-map-1.0.2.tgz#2b4213a4285ca3a8cd2e696782c9964f887524e7" @@ -30969,7 +30883,7 @@ tapable@^1.0.0, tapable@^1.1.3: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tapable@^2.1.1, tapable@^2.2.0: +tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== @@ -31597,13 +31511,14 @@ ts-pnp@^1.1.6: resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== -tsconfig-paths-webpack-plugin@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.1.0.tgz#3c6892c5e7319c146eee1e7302ed9e6f2be4f763" - integrity sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA== +tsconfig-paths-webpack-plugin@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.2.0.tgz#f7459a8ed1dd4cf66ad787aefc3d37fff3cf07fc" + integrity sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA== dependencies: chalk "^4.1.0" enhanced-resolve "^5.7.0" + tapable "^2.2.1" tsconfig-paths "^4.1.2" tsconfig-paths@^3.14.2: @@ -32352,12 +32267,7 @@ uuid-browser@^3.1.0: resolved "https://registry.yarnpkg.com/uuid-browser/-/uuid-browser-3.1.0.tgz#0f05a40aef74f9e5951e20efbf44b11871e56410" integrity sha1-DwWkCu90+eWVHiDvv0SxGHHlZBA= -uuid@9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" - integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== - -uuid@^10.0.0: +uuid@10.0.0, uuid@^10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294" integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ== @@ -33018,10 +32928,10 @@ watchpack@^2.2.0, watchpack@^2.4.1: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" -watskeburt@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/watskeburt/-/watskeburt-4.1.0.tgz#3c0227669be646a97424b631164b1afe3d4d5344" - integrity sha512-KkY5H51ajqy9HYYI+u9SIURcWnqeVVhdH0I+ab6aXPGHfZYxgRCwnR6Lm3+TYB6jJVt5jFqw4GAKmwf1zHmGQw== +watskeburt@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/watskeburt/-/watskeburt-4.2.2.tgz#e24f0afc40b7ecf511bf24c285b91dee2df4f4a5" + integrity sha512-AOCg1UYxWpiHW1tUwqpJau8vzarZYTtzl2uu99UptBmbzx6kOzCGMfRLF6KIRX4PYekmryn89MzxlRNkL66YyA== wbuf@^1.1.0, wbuf@^1.7.3: version "1.7.3"