diff --git a/.buildkite/scripts/steps/storybooks/build_and_upload.ts b/.buildkite/scripts/steps/storybooks/build_and_upload.ts
index 483a5c28a295b..b1135490a2023 100644
--- a/.buildkite/scripts/steps/storybooks/build_and_upload.ts
+++ b/.buildkite/scripts/steps/storybooks/build_and_upload.ts
@@ -18,15 +18,16 @@ const STORYBOOKS = [
'canvas',
'cases',
'cell_actions',
- 'coloring',
'chart_icons',
+ 'cloud_security_posture_packages',
+ 'coloring',
'content_management_examples',
'custom_integrations',
'dashboard_enhanced',
'dashboard',
'data',
- 'logs_explorer',
'embeddable',
+ 'esql_editor',
'expression_error',
'expression_image',
'expression_metric',
@@ -34,28 +35,28 @@ const STORYBOOKS = [
'expression_reveal_image',
'expression_shape',
'expression_tagcloud',
- 'management',
'fleet',
'grouping',
'home',
'infra',
'kibana_react',
+ 'language_documentation_popover',
'lists',
- 'observability',
+ 'logs_explorer',
+ 'management',
'observability_ai_assistant',
'observability_inventory',
'observability_shared',
+ 'observability',
'presentation',
- 'security_solution',
+ 'random_sampling',
'security_solution_packages',
+ 'security_solution',
'serverless',
'shared_ux',
'triggers_actions_ui',
'ui_actions_enhanced',
- 'language_documentation_popover',
'unified_search',
- 'random_sampling',
- 'esql_editor',
];
const GITHUB_CONTEXT = 'Build and Publish Storybooks';
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 3e73a2a40a388..80d9c8b64e9e6 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1911,10 +1911,10 @@ x-pack/plugins/osquery @elastic/security-defend-workflows
/x-pack/plugins/security_solution/public/detections/components/osquery @elastic/security-defend-workflows
# Cloud Defend
-/x-pack/plugins/cloud_defend/ @elastic/kibana-cloud-security-posture
/x-pack/plugins/security_solution/public/cloud_defend @elastic/kibana-cloud-security-posture
# Cloud Security Posture
+x-pack/packages/kbn-cloud-security-posture @elastic/kibana-cloud-security-posture
/x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.* @elastic/kibana-cloud-security-posture
/x-pack/plugins/security_solution/public/cloud_security_posture @elastic/kibana-cloud-security-posture
/x-pack/test/api_integration/apis/cloud_security_posture/ @elastic/kibana-cloud-security-posture
diff --git a/docs/api/synthetics/params/edit-param.asciidoc b/docs/api/synthetics/params/edit-param.asciidoc
index e615dd0c0bd1f..07a2568207dfe 100644
--- a/docs/api/synthetics/params/edit-param.asciidoc
+++ b/docs/api/synthetics/params/edit-param.asciidoc
@@ -26,13 +26,13 @@ You must have `all` privileges for the *Synthetics* feature in the *{observabili
[[parameter-edit-request-body]]
==== Request body
-The request body should contain the following attributes:
+The request body can contain the following attributes, it can't be empty at least one attribute is required.:
`key`::
-(Required, string) The key of the parameter.
+(Optional, string) The key of the parameter.
`value`::
-(Required, string) The updated value associated with the parameter.
+(Optional, string) The updated value associated with the parameter.
`description`::
(Optional, string) The updated description of the parameter.
diff --git a/packages/kbn-optimizer/src/worker/webpack.config.ts b/packages/kbn-optimizer/src/worker/webpack.config.ts
index 52a837724480d..96a17a6ae7229 100644
--- a/packages/kbn-optimizer/src/worker/webpack.config.ts
+++ b/packages/kbn-optimizer/src/worker/webpack.config.ts
@@ -259,6 +259,27 @@ export function getWebpackConfig(
},
},
},
+ {
+ test: /\.js$/,
+ include: /node_modules[\\\/]@dagrejs/,
+ use: {
+ loader: 'babel-loader',
+ options: {
+ envName: worker.dist ? 'production' : 'development',
+ presets: ['@babel/preset-env'], // Doesn't work with BABEL_PRESET
+ plugins: ['@babel/plugin-proposal-class-properties'],
+ },
+ },
+ },
+ {
+ test: /node_modules[\/\\]@?xyflow[\/\\].*.js$/,
+ loaders: 'babel-loader',
+ options: {
+ envName: worker.dist ? 'production' : 'development',
+ presets: [BABEL_PRESET],
+ plugins: ['@babel/plugin-transform-logical-assignment-operators'],
+ },
+ },
{
test: /\.(html|md|txt|tmpl)$/,
use: {
diff --git a/packages/kbn-storybook/src/webpack.config.ts b/packages/kbn-storybook/src/webpack.config.ts
index b03d78dbbc190..fad795a1e4619 100644
--- a/packages/kbn-storybook/src/webpack.config.ts
+++ b/packages/kbn-storybook/src/webpack.config.ts
@@ -136,6 +136,25 @@ export default ({ config: storybookConfig }: { config: Configuration }) => {
},
},
},
+ {
+ test: /\.js$/,
+ include: /node_modules[\\\/]@dagrejs/,
+ use: {
+ loader: 'babel-loader',
+ options: {
+ presets: ['@babel/preset-env'], // Doesn't work with @kbn/babel-preset/webpack_preset
+ plugins: ['@babel/plugin-proposal-class-properties'],
+ },
+ },
+ },
+ {
+ test: /node_modules[\/\\]@?xyflow[\/\\].*.js$/,
+ loaders: 'babel-loader',
+ options: {
+ presets: [require.resolve('@kbn/babel-preset/webpack_preset')],
+ plugins: ['@babel/plugin-transform-logical-assignment-operators'],
+ },
+ },
],
},
plugins: [new IgnoreNotFoundExportPlugin()],
diff --git a/test/functional/apps/discover/group3/_lens_vis.ts b/test/functional/apps/discover/group3/_lens_vis.ts
index db526fe978610..5e13c8bbb243c 100644
--- a/test/functional/apps/discover/group3/_lens_vis.ts
+++ b/test/functional/apps/discover/group3/_lens_vis.ts
@@ -110,8 +110,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
return seriesType;
}
- // Failing: See https://github.com/elastic/kibana/issues/197342
- describe.skip('discover lens vis', function () {
+ describe('discover lens vis', function () {
before(async () => {
await security.testUser.setRoles(['kibana_admin', 'test_logstash_reader']);
await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional');
@@ -616,8 +615,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
expect(await getCurrentVisTitle()).to.be('Pie');
await testSubjects.existOrFail('partitionVisChart');
- await discover.chooseLensSuggestion('barVerticalStacked');
- await changeVisShape('Line');
+ await discover.chooseLensSuggestion('waffle');
+ await changeVisShape('Treemap');
await testSubjects.existOrFail('unsavedChangesBadge');
await discover.saveUnsavedChanges();
@@ -626,8 +625,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await discover.waitUntilSearchingHasFinished();
await testSubjects.missingOrFail('unsavedChangesBadge');
- expect(await getCurrentVisTitle()).to.be('Line');
- await testSubjects.existOrFail('xyVisChart');
+ expect(await getCurrentVisTitle()).to.be('Treemap');
+ await testSubjects.existOrFail('partitionVisChart');
});
it('should close lens flyout on revert changes', async () => {
diff --git a/x-pack/packages/kbn-cloud-security-posture/common/kibana.jsonc b/x-pack/packages/kbn-cloud-security-posture/common/kibana.jsonc
index 21721cfb69f44..f3bd18f10c7a8 100644
--- a/x-pack/packages/kbn-cloud-security-posture/common/kibana.jsonc
+++ b/x-pack/packages/kbn-cloud-security-posture/common/kibana.jsonc
@@ -1,6 +1,5 @@
-
{
- "id": "@kbn/cloud-security-posture-common",
- "owner": "@elastic/kibana-cloud-security-posture",
- "type": "shared-common"
- }
\ No newline at end of file
+ "id": "@kbn/cloud-security-posture-common",
+ "owner": "@elastic/kibana-cloud-security-posture",
+ "type": "shared-common"
+}
diff --git a/x-pack/packages/kbn-cloud-security-posture/common/package.json b/x-pack/packages/kbn-cloud-security-posture/common/package.json
index 8ead7b37ceeb6..37276e735987d 100644
--- a/x-pack/packages/kbn-cloud-security-posture/common/package.json
+++ b/x-pack/packages/kbn-cloud-security-posture/common/package.json
@@ -1,8 +1,8 @@
{
- "name": "@kbn/cloud-security-posture-common",
- "private": true,
- "version": "1.0.0",
- "license": "Elastic License 2.0",
- "description": "Shared components for cloud security posture, both client and server side",
- "sideEffects": false
- }
\ No newline at end of file
+ "name": "@kbn/cloud-security-posture-common",
+ "private": true,
+ "version": "1.0.0",
+ "license": "Elastic License 2.0",
+ "description": "Shared components for cloud security posture, both client and server side",
+ "sideEffects": false
+}
diff --git a/x-pack/packages/kbn-cloud-security-posture/common/schema/graph/v1.ts b/x-pack/packages/kbn-cloud-security-posture/common/schema/graph/v1.ts
index f27ddb397c57c..3d37331b4cc5d 100644
--- a/x-pack/packages/kbn-cloud-security-posture/common/schema/graph/v1.ts
+++ b/x-pack/packages/kbn-cloud-security-posture/common/schema/graph/v1.ts
@@ -71,8 +71,6 @@ export const groupNodeDataSchema = schema.allOf([
export const labelNodeDataSchema = schema.allOf([
nodeBaseDataSchema,
schema.object({
- source: schema.string(),
- target: schema.string(),
shape: schema.literal('label'),
parentId: schema.maybe(schema.string()),
color: colorSchema,
@@ -82,8 +80,6 @@ export const labelNodeDataSchema = schema.allOf([
export const edgeDataSchema = schema.object({
id: schema.string(),
source: schema.string(),
- sourceShape: nodeShapeSchema,
target: schema.string(),
- targetShape: nodeShapeSchema,
color: colorSchema,
});
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/README.md b/x-pack/packages/kbn-cloud-security-posture/graph/README.md
index c67ca622fe414..bde99acb4e7a6 100644
--- a/x-pack/packages/kbn-cloud-security-posture/graph/README.md
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/README.md
@@ -7,11 +7,104 @@ security solution plugin.
## How to use this
-Standalone examples will follow. In the meantime check out storybook to view the graph's progress.
+### Step 1: Import the Component
-## The most important public api members
+First, import the `Graph` component into your desired file.
-- GraphComponent itself (comming soon..)
+```tsx
+import { Graph } from '@kbn/cloud-security-posture-graph';
+```
+
+### Step 2: Prepare the Data
+
+Create the nodes and edges data models. These should follow the `NodeViewModel` and `EdgeViewModel` interfaces.
+
+```tsx
+const nodes: NodeViewModel[] = [
+ {
+ id: 'node1',
+ label: 'Node 1',
+ color: 'primary',
+ shape: 'ellipse',
+ icon: 'user',
+ },
+ {
+ id: 'node2',
+ label: 'Node 2',
+ color: 'primary',
+ shape: 'hexagon',
+ icon: 'questionInCircle',
+ },
+];
+
+const edges: EdgeViewModel[] = [
+ {
+ id: 'edge1',
+ source: 'node1',
+ target: 'node2',
+ color: 'primary',
+ },
+];
+```
+
+### Step 3: Render the Component
+
+Use the `Graph` component in your JSX/TSX, passing the nodes, edges, and interactivity flag as props.
+
+```tsx
+
+```
+
+### Example Usage
+
+Here is a complete example of how to use the `Graph` component in a React component.
+
+```tsx
+import React from 'react';
+import { Graph } from '@kbn/cloud-security-posture-graph';
+import type { NodeViewModel, EdgeViewModel } from '@kbn/cloud-security-posture-graph';
+
+const App: React.FC = () => {
+ const nodes: NodeViewModel[] = [
+ {
+ id: 'node1',
+ label: 'Node 1',
+ color: 'primary',
+ shape: 'ellipse',
+ icon: 'user',
+ },
+ {
+ id: 'node2',
+ label: 'Node 2',
+ color: 'primary',
+ shape: 'hexagon',
+ icon: 'questionInCircle',
+ },
+ ];
+
+ const edges: EdgeViewModel[] = [
+ {
+ id: 'edge1',
+ source: 'node1',
+ target: 'node2',
+ color: 'primary',
+ },
+ ];
+
+ return (
+
+
Graph Visualization
+
+
+ );
+};
+
+export default App;
+```
+
+### Storybook Example
+
+You can also see how the `Graph` component is used in the Storybook file `graph_layout.stories.tsx`.
### Extras
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/index.ts b/x-pack/packages/kbn-cloud-security-posture/graph/index.ts
index 1fec1c76430eb..c50969cfd6402 100644
--- a/x-pack/packages/kbn-cloud-security-posture/graph/index.ts
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/index.ts
@@ -4,3 +4,5 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
+
+export * from './src/components';
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/jest.config.js b/x-pack/packages/kbn-cloud-security-posture/graph/jest.config.js
index 9e295d0f4d626..3b8fbbd9384a4 100644
--- a/x-pack/packages/kbn-cloud-security-posture/graph/jest.config.js
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/jest.config.js
@@ -9,4 +9,6 @@ module.exports = {
preset: '@kbn/test',
roots: ['/x-pack/packages/kbn-cloud-security-posture/graph'],
rootDir: '../../../..',
+ setupFiles: ['jest-canvas-mock'],
+ setupFilesAfterEnv: ['/x-pack/packages/kbn-cloud-security-posture/graph/setup_tests.ts'],
};
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/kibana.jsonc b/x-pack/packages/kbn-cloud-security-posture/graph/kibana.jsonc
index 455f1607a22a2..513861b347059 100644
--- a/x-pack/packages/kbn-cloud-security-posture/graph/kibana.jsonc
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/kibana.jsonc
@@ -1,5 +1,5 @@
{
- "type": "shared-browser",
"id": "@kbn/cloud-security-posture-graph",
- "owner": "@elastic/kibana-cloud-security-posture"
+ "owner": "@elastic/kibana-cloud-security-posture",
+ "type": "shared-browser"
}
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/setup_tests.ts b/x-pack/packages/kbn-cloud-security-posture/graph/setup_tests.ts
new file mode 100644
index 0000000000000..7f6858c0fd40d
--- /dev/null
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/setup_tests.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.
+ */
+
+// eslint-disable-next-line @kbn/imports/no_boundary_crossing
+import { mockReactFlow } from './src/components/mock/react_flow';
+// eslint-disable-next-line import/no-extraneous-dependencies
+import '@testing-library/jest-dom';
+
+mockReactFlow();
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/graph/graph.test.tsx b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/graph/graph.test.tsx
new file mode 100644
index 0000000000000..18ba84207f962
--- /dev/null
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/graph/graph.test.tsx
@@ -0,0 +1,110 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { render } from '@testing-library/react';
+import React from 'react';
+import { Graph, type GraphProps } from './graph';
+import { TestProviders } from '../mock/test_providers';
+
+const renderGraphPreview = (props: GraphProps) =>
+ render(
+
+
+
+ );
+
+describe('', () => {
+ it('should render empty graph', () => {
+ const { container } = renderGraphPreview({
+ nodes: [],
+ edges: [],
+ interactive: false,
+ });
+
+ expect(container).not.toBeNull();
+ const nodes = container.querySelectorAll('.react-flow__nodes .react-flow__node');
+ expect(nodes).toHaveLength(0);
+ });
+
+ it('should render hexagon node', () => {
+ const { container } = renderGraphPreview({
+ nodes: [
+ {
+ id: '1',
+ label: 'Node 1',
+ color: 'primary',
+ shape: 'hexagon',
+ },
+ ],
+ edges: [],
+ interactive: false,
+ });
+
+ const nodeEl = container.querySelector('[data-id="1"]');
+ expect(nodeEl).not.toBeNull();
+ expect(nodeEl?.textContent).toBe('Node 1');
+ });
+
+ it('should render label node', () => {
+ const { container } = renderGraphPreview({
+ nodes: [
+ {
+ id: '2',
+ label: 'Node 2',
+ color: 'primary',
+ shape: 'label',
+ },
+ ],
+ edges: [],
+ interactive: false,
+ });
+
+ const nodeEl = container.querySelector('[data-id="2"]');
+ expect(nodeEl).not.toBeNull();
+ expect(nodeEl?.textContent).toBe('Node 2');
+ });
+
+ it('should render 2 nodes connected', () => {
+ const { container } = renderGraphPreview({
+ nodes: [
+ {
+ id: '1',
+ label: 'Node 1',
+ color: 'primary',
+ shape: 'hexagon',
+ },
+ {
+ id: '2',
+ label: 'Node 2',
+ color: 'primary',
+ shape: 'label',
+ },
+ ],
+ edges: [
+ {
+ id: 'a(1)-b(2)',
+ color: 'primary',
+ source: '1',
+ target: '2',
+ },
+ ],
+ interactive: false,
+ });
+
+ const srcNodeEl = container.querySelector('[data-id="1"]');
+ expect(srcNodeEl).not.toBeNull();
+ expect(srcNodeEl?.textContent).toBe('Node 1');
+
+ const targetNodeEl = container.querySelector('[data-id="2"]');
+ expect(targetNodeEl).not.toBeNull();
+ expect(targetNodeEl?.textContent).toBe('Node 2');
+
+ // TODO: Fix this test (currently it is not rendered in xyflow version 12) https://github.com/xyflow/xyflow/issues/716#issuecomment-2414721074
+ // const edgeEl = container.querySelector('[data-id="a(1)-b(2)"]');
+ // expect(edgeEl).not.toBeNull();
+ });
+});
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/graph/graph.tsx b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/graph/graph.tsx
new file mode 100644
index 0000000000000..eca9872d73897
--- /dev/null
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/graph/graph.tsx
@@ -0,0 +1,204 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license 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, useRef, useState, useCallback } from 'react';
+import {
+ Background,
+ Controls,
+ Position,
+ ReactFlow,
+ useEdgesState,
+ useNodesState,
+} from '@xyflow/react';
+import type { Edge, Node } from '@xyflow/react';
+import type { CommonProps } from '@elastic/eui';
+import { SvgDefsMarker } from '../edge/styles';
+import {
+ HexagonNode,
+ PentagonNode,
+ EllipseNode,
+ RectangleNode,
+ DiamondNode,
+ LabelNode,
+ EdgeGroupNode,
+} from '../node';
+import { layoutGraph } from './layout_graph';
+import { DefaultEdge } from '../edge';
+import type { EdgeViewModel, NodeViewModel } from '../types';
+
+import '@xyflow/react/dist/style.css';
+
+export interface GraphProps extends CommonProps {
+ nodes: NodeViewModel[];
+ edges: EdgeViewModel[];
+ interactive: boolean;
+}
+
+const nodeTypes = {
+ hexagon: HexagonNode,
+ pentagon: PentagonNode,
+ ellipse: EllipseNode,
+ rectangle: RectangleNode,
+ diamond: DiamondNode,
+ label: LabelNode,
+ group: EdgeGroupNode,
+};
+
+const edgeTypes = {
+ default: DefaultEdge,
+};
+
+/**
+ * Graph component renders a graph visualization using ReactFlow.
+ * It takes nodes and edges as input and provides interactive controls
+ * for panning, zooming, and manipulating the graph.
+ *
+ * @component
+ * @param {GraphProps} props - The properties for the Graph component.
+ * @param {NodeViewModel[]} props.nodes - Array of node view models to be rendered in the graph.
+ * @param {EdgeViewModel[]} props.edges - Array of edge view models to be rendered in the graph.
+ * @param {boolean} props.interactive - Flag to enable or disable interactivity (panning, zooming, etc.).
+ * @param {CommonProps} [props.rest] - Additional common properties.
+ *
+ * @returns {JSX.Element} The rendered Graph component.
+ */
+export const Graph: React.FC = ({ nodes, edges, interactive, ...rest }) => {
+ const layoutCalled = useRef(false);
+ const [isGraphLocked, setIsGraphLocked] = useState(interactive);
+ const { initialNodes, initialEdges } = useMemo(
+ () => processGraph(nodes, edges, isGraphLocked),
+ [nodes, edges, isGraphLocked]
+ );
+
+ const [nodesState, setNodes, onNodesChange] = useNodesState(initialNodes);
+ const [edgesState, _setEdges, onEdgesChange] = useEdgesState(initialEdges);
+
+ if (!layoutCalled.current) {
+ const { nodes: layoutedNodes } = layoutGraph(nodesState, edgesState);
+ setNodes(layoutedNodes);
+ layoutCalled.current = true;
+ }
+
+ const onInteractiveStateChange = useCallback(
+ (interactiveStatus: boolean): void => {
+ setIsGraphLocked(interactiveStatus);
+ setNodes((prevNodes) =>
+ prevNodes.map((node) => ({
+ ...node,
+ data: {
+ ...node.data,
+ interactive: interactiveStatus,
+ },
+ }))
+ );
+ },
+ [setNodes]
+ );
+
+ return (
+
+
+ {
+ window.requestAnimationFrame(() => xyflow.fitView());
+
+ // When the graph is not initialized as interactive, we need to fit the view on resize
+ if (!interactive) {
+ const resizeObserver = new ResizeObserver(() => {
+ xyflow.fitView();
+ });
+ resizeObserver.observe(document.querySelector('.react-flow') as Element);
+ return () => resizeObserver.disconnect();
+ }
+ }}
+ nodeTypes={nodeTypes}
+ edgeTypes={edgeTypes}
+ nodes={nodesState}
+ edges={edgesState}
+ onNodesChange={onNodesChange}
+ onEdgesChange={onEdgesChange}
+ proOptions={{ hideAttribution: true }}
+ panOnDrag={isGraphLocked}
+ zoomOnScroll={isGraphLocked}
+ zoomOnPinch={isGraphLocked}
+ zoomOnDoubleClick={isGraphLocked}
+ preventScrolling={isGraphLocked}
+ nodesDraggable={interactive && isGraphLocked}
+ maxZoom={1.3}
+ >
+ {interactive && }
+
+
+
+ );
+};
+
+const processGraph = (
+ nodesModel: NodeViewModel[],
+ edgesModel: EdgeViewModel[],
+ interactive: boolean
+): {
+ initialNodes: Array>;
+ initialEdges: Array>;
+} => {
+ const nodesById: { [key: string]: NodeViewModel } = {};
+
+ const initialNodes = nodesModel.map((nodeData) => {
+ nodesById[nodeData.id] = nodeData;
+
+ const node: Node = {
+ id: nodeData.id,
+ type: nodeData.shape,
+ data: { ...nodeData, interactive },
+ position: { x: 0, y: 0 }, // Default position, should be updated later
+ };
+
+ if (node.type === 'group' && nodeData.shape === 'group') {
+ node.sourcePosition = Position.Right;
+ node.targetPosition = Position.Left;
+ node.resizing = false;
+ node.focusable = false;
+ } else if (nodeData.shape === 'label' && nodeData.parentId) {
+ node.parentId = nodeData.parentId;
+ node.extent = 'parent';
+ node.expandParent = false;
+ node.draggable = false;
+ }
+
+ return node;
+ });
+
+ const initialEdges: Array> = edgesModel.map((edgeData) => {
+ const isIn =
+ nodesById[edgeData.source].shape !== 'label' && nodesById[edgeData.target].shape === 'group';
+ const isInside =
+ nodesById[edgeData.source].shape === 'group' && nodesById[edgeData.target].shape === 'label';
+ const isOut =
+ nodesById[edgeData.source].shape === 'label' && nodesById[edgeData.target].shape === 'group';
+ const isOutside =
+ nodesById[edgeData.source].shape === 'group' && nodesById[edgeData.target].shape !== 'label';
+
+ return {
+ id: edgeData.id,
+ type: 'default',
+ source: edgeData.source,
+ sourceHandle: isInside ? 'inside' : isOutside ? 'outside' : undefined,
+ target: edgeData.target,
+ targetHandle: isIn ? 'in' : isOut ? 'out' : undefined,
+ focusable: false,
+ selectable: false,
+ data: {
+ ...edgeData,
+ sourceShape: nodesById[edgeData.source].shape,
+ targetShape: nodesById[edgeData.target].shape,
+ },
+ };
+ });
+
+ return { initialNodes, initialEdges };
+};
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/graph/layout_graph.ts b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/graph/layout_graph.ts
index d9f637483c115..868461f99cdee 100644
--- a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/graph/layout_graph.ts
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/graph/layout_graph.ts
@@ -6,18 +6,16 @@
*/
import Dagre from '@dagrejs/dagre';
-import type {
- EdgeDataModel,
- NodeDataModel,
-} from '@kbn/cloud-security-posture-common/types/graph/latest';
-import type { NodeViewModel, Size } from '../types';
+import type { Node, Edge } from '@xyflow/react';
+import type { EdgeViewModel, NodeViewModel, Size } from '../types';
import { calcLabelSize } from './utils';
+import { GroupStyleOverride, NODE_HEIGHT, NODE_WIDTH } from '../node/styles';
export const layoutGraph = (
- nodes: NodeDataModel[],
- edges: EdgeDataModel[]
-): { nodes: NodeViewModel[] } => {
- const nodesById: { [key: string]: NodeViewModel } = {};
+ nodes: Array>,
+ edges: Array>
+): { nodes: Array> } => {
+ const nodesById: { [key: string]: Node } = {};
const graphOpts = {
compound: true,
};
@@ -29,28 +27,27 @@ export const layoutGraph = (
edges.forEach((edge) => g.setEdge(edge.source, edge.target));
nodes.forEach((node) => {
- let size = { width: 90, height: 90 };
- const position = { x: 0, y: 0 };
+ let size = { width: NODE_WIDTH, height: node.measured?.height ?? NODE_HEIGHT };
- if (node.shape === 'label') {
- size = calcLabelSize(node.label);
+ if (node.data.shape === 'label') {
+ size = calcLabelSize(node.data.label);
// TODO: waiting for a fix: https://github.com/dagrejs/dagre/issues/238
// if (node.parentId) {
// g.setParent(node.id, node.parentId);
// }
- } else if (node.shape === 'group') {
+ } else if (node.data.shape === 'group') {
const res = layoutGroupChildren(node, nodes);
size = res.size;
res.children.forEach((child) => {
- nodesById[child.id] = { ...child };
+ nodesById[child.data.id] = child;
});
}
if (!nodesById[node.id]) {
- nodesById[node.id] = { ...node, position };
+ nodesById[node.id] = node;
}
g.setNode(node.id, {
@@ -61,8 +58,8 @@ export const layoutGraph = (
Dagre.layout(g);
- const nodesViewModel: NodeViewModel[] = nodes.map((nodeData) => {
- const dagreNode = g.node(nodeData.id);
+ const layoutedNodes = nodes.map((node) => {
+ const dagreNode = g.node(node.data.id);
// We are shifting the dagre node position (anchor=center center) to the top left
// so it matches the React Flow node anchor point (top left).
@@ -70,37 +67,43 @@ export const layoutGraph = (
const y = dagreNode.y - (dagreNode.height ?? 0) / 2;
// For grouped nodes, we want to keep the original position relative to the parent
- if (nodeData.shape === 'label' && nodeData.parentId) {
+ if (node.data.shape === 'label' && node.data.parentId) {
return {
- ...nodeData,
- position: nodesById[nodeData.id].position,
+ ...node,
+ position: nodesById[node.data.id].position,
};
- } else if (nodeData.shape === 'group') {
+ } else if (node.data.shape === 'group') {
return {
- ...nodeData,
+ ...node,
position: { x, y },
- size: {
+ style: GroupStyleOverride({
width: dagreNode.width,
height: dagreNode.height,
- },
+ }),
+ };
+ } else if (node.data.shape === 'label') {
+ return {
+ ...node,
+ position: { x, y },
+ };
+ } else {
+ // Align nodes to labels by shifting the node position by it's label height
+ return {
+ ...node,
+ position: { x, y: y + (dagreNode.height - NODE_HEIGHT) / 2 },
};
}
-
- return {
- ...nodeData,
- position: { x, y },
- };
});
- return { nodes: nodesViewModel };
+ return { nodes: layoutedNodes };
};
const layoutGroupChildren = (
- groupNode: NodeDataModel,
- nodes: NodeDataModel[]
-): { size: Size; children: NodeViewModel[] } => {
+ groupNode: Node,
+ nodes: Array>
+): { size: Size; children: Array> } => {
const children = nodes.filter(
- (child) => child.shape === 'label' && child.parentId === groupNode.id
+ (child) => child.data.shape === 'label' && child.parentId === groupNode.id
);
const STACK_VERTICAL_PADDING = 20;
@@ -108,7 +111,7 @@ const layoutGroupChildren = (
const PADDING = 20;
const stackSize = children.length;
const allChildrenHeight = children.reduce(
- (prevHeight, node) => prevHeight + calcLabelSize(node.label).height,
+ (prevHeight, node) => prevHeight + calcLabelSize(node.data.label).height,
0
);
const stackHeight = Math.max(
@@ -118,23 +121,21 @@ const layoutGroupChildren = (
const space = (stackHeight - allChildrenHeight) / (stackSize - 1);
const groupNodeWidth = children.reduce((acc, child) => {
- const currLblWidth = PADDING * 2 + calcLabelSize(child.label).width;
+ const currLblWidth = PADDING * 2 + calcLabelSize(child.data.label).width;
return Math.max(acc, currLblWidth);
}, 0);
// Layout children relative to parent
- const positionedChildren: NodeViewModel[] = children.map((child, index) => {
- const childSize = calcLabelSize(child.label);
- const childPosition = {
+ children.forEach((child, index) => {
+ const childSize = calcLabelSize(child.data.label);
+ child.position = {
x: groupNodeWidth / 2 - childSize.width / 2,
y: index * (childSize.height * 2 + space),
};
-
- return { ...child, position: childPosition };
});
return {
size: { width: groupNodeWidth, height: stackHeight },
- children: positionedChildren,
+ children,
};
};
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/dagree_layout_graph.stories.tsx b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/graph_layout.stories.tsx
similarity index 76%
rename from x-pack/packages/kbn-cloud-security-posture/graph/src/components/dagree_layout_graph.stories.tsx
rename to x-pack/packages/kbn-cloud-security-posture/graph/src/components/graph_layout.stories.tsx
index 94bc7e8af353b..140e81238d390 100644
--- a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/dagree_layout_graph.stories.tsx
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/graph_layout.stories.tsx
@@ -7,68 +7,40 @@
import React from 'react';
import { ThemeProvider } from '@emotion/react';
-import {
- ReactFlow,
- Controls,
- Background,
- Node,
- Edge,
- Position,
- useNodesState,
- useEdgesState,
-} from '@xyflow/react';
import { Story } from '@storybook/react';
-import type {
- EdgeDataModel,
- LabelNodeDataModel,
- NodeDataModel,
-} from '@kbn/cloud-security-posture-common/types/graph/latest';
import { Writable } from '@kbn/utility-types';
-import {
- HexagonNode,
- PentagonNode,
- EllipseNode,
- RectangleNode,
- DiamondNode,
- LabelNode,
- EdgeGroupNode,
-} from './node';
-import type { NodeViewModel } from './types';
-import { DefaultEdge } from './edge';
-import { SvgDefsMarker } from './edge/styles';
-import { GroupStyleOverride } from './node/styles';
-
-import '@xyflow/react/dist/style.css';
-import { layoutGraph } from './graph/layout_graph';
+import { css } from '@emotion/react';
+import type {
+ EdgeViewModel,
+ LabelNodeViewModel,
+ NodeViewModel,
+ EntityNodeViewModel,
+ GroupNodeViewModel,
+} from '.';
+import { Graph } from '.';
export default {
- title: 'Components/Graph Components/Dagree Layout Graph',
+ title: 'Components/Graph Components/Graph Layout',
description: 'CDR - Graph visualization',
-};
-
-const nodeTypes = {
- hexagon: HexagonNode,
- pentagon: PentagonNode,
- ellipse: EllipseNode,
- rectangle: RectangleNode,
- diamond: DiamondNode,
- label: LabelNode,
- group: EdgeGroupNode,
-};
-
-const edgeTypes = {
- default: DefaultEdge,
+ argTypes: {
+ interactive: { control: 'boolean', defaultValue: true },
+ },
};
interface GraphData {
- nodes: NodeDataModel[];
- edges: EdgeDataModel[];
+ nodes: NodeViewModel[];
+ edges: EdgeViewModel[];
interactive: boolean;
}
+type EnhancedNodeViewModel =
+ | EntityNodeViewModel
+ | GroupNodeViewModel
+ | (LabelNodeViewModel & { source: string; target: string });
+
const extractEdges = (
- graphData: NodeDataModel[]
-): { nodes: NodeDataModel[]; edges: EdgeDataModel[] } => {
+ graphData: EnhancedNodeViewModel[]
+): { nodes: NodeViewModel[]; edges: EdgeViewModel[] } => {
// Process nodes, transform nodes of id in the format of a(source)-b(target) to edges from a to label and from label to b
// If there are multiple edges from a to b, create a parent node and group the labels under it. The parent node will be a group node.
// Connect from a to the group node and from the group node to all the labels. and from the labels to the group again and from the group to b.
@@ -77,14 +49,14 @@ const extractEdges = (
[key: string]: { source: string; target: string; edgesStacked: number; edges: string[] };
} = {};
const labelsMetadata: {
- [key: string]: { source: string; target: string; labelsNodes: LabelNodeDataModel[] };
+ [key: string]: { source: string; target: string; labelsNodes: LabelNodeViewModel[] };
} = {};
- const nodes: { [key: string]: NodeDataModel } = {};
- const edges: EdgeDataModel[] = [];
+ const nodes: { [key: string]: NodeViewModel } = {};
+ const edges: EdgeViewModel[] = [];
graphData.forEach((node) => {
if (node.shape === 'label') {
- const labelNode = { ...node, id: `${node.id}label(${node.label})` };
+ const labelNode: LabelNodeViewModel = { ...node, id: `${node.id}label(${node.label})` };
const { source, target } = node;
if (labelsMetadata[node.id]) {
@@ -119,7 +91,7 @@ const extractEdges = (
Object.values(labelsMetadata).forEach((edge) => {
if (edge.labelsNodes.length > 1) {
- const groupNode: NodeDataModel = {
+ const groupNode: NodeViewModel = {
id: `grp(a(${edge.source})-b(${edge.target}))`,
shape: 'group',
};
@@ -143,7 +115,7 @@ const extractEdges = (
color: edge.labelsNodes[0].color,
});
- edge.labelsNodes.forEach((labelNode: Writable) => {
+ edge.labelsNodes.forEach((labelNode: Writable) => {
labelNode.parentId = groupNode.id;
edges.push({
@@ -189,28 +161,18 @@ const extractEdges = (
return { nodes: Object.values(nodes).reverse(), edges };
};
-const Template: Story = ({ nodes, edges }: GraphData) => {
- const { initialNodes, initialEdges } = processGraph(nodes, edges);
-
- const [nodesState, _setNodes, onNodesChange] = useNodesState(initialNodes);
- const [edgesState, _setEdges, onEdgesChange] = useEdgesState(initialEdges);
-
+const Template: Story = ({ nodes, edges, interactive }: GraphData) => {
return (
-
-
-
-
-
+
);
};
@@ -359,8 +321,8 @@ GroupWithWarningAPIMock.args = {
],
};
-export const Graph = Template.bind({});
-const baseGraph: NodeDataModel[] = [
+export const LargeGraph = Template.bind({});
+const baseGraph: EnhancedNodeViewModel[] = [
{
id: 'siem-windows',
label: '',
@@ -483,7 +445,7 @@ const baseGraph: NodeDataModel[] = [
},
];
-Graph.args = {
+LargeGraph.args = {
...extractEdges(baseGraph),
};
@@ -541,67 +503,3 @@ GraphStackedEdgeCases.args = {
},
]),
};
-
-function processGraph(
- nodesModel: NodeDataModel[],
- edgesModel: EdgeDataModel[]
-): {
- initialNodes: Node[];
- initialEdges: Edge[];
-} {
- const { nodes: nodesViewModel } = layoutGraph(nodesModel, edgesModel);
-
- const nodesById: { [key: string]: NodeViewModel } = {};
-
- const initialNodes = nodesViewModel.map((nodeData) => {
- nodesById[nodeData.id] = nodeData;
-
- const node: Node = {
- id: nodeData.id,
- type: nodeData.shape,
- data: { ...nodeData, interactive: true },
- position: nodeData.position,
- draggable: true,
- };
-
- if (node.type === 'group' && nodeData.shape === 'group') {
- node.sourcePosition = Position.Right;
- node.targetPosition = Position.Left;
- node.resizing = false;
- node.style = GroupStyleOverride({
- width: nodeData.size?.width ?? 0,
- height: nodeData.size?.height ?? 0,
- });
- } else if (nodeData.shape === 'label' && nodeData.parentId) {
- node.parentId = nodeData.parentId;
- node.extent = 'parent';
- node.expandParent = false;
- node.draggable = false;
- }
-
- return node;
- });
-
- const initialEdges: Edge[] = edgesModel.map((edgeData) => {
- const isIn =
- nodesById[edgeData.source].shape !== 'label' && nodesById[edgeData.target].shape === 'group';
- const isInside =
- nodesById[edgeData.source].shape === 'group' && nodesById[edgeData.target].shape === 'label';
- const isOut =
- nodesById[edgeData.source].shape === 'label' && nodesById[edgeData.target].shape === 'group';
- const isOutside =
- nodesById[edgeData.source].shape === 'group' && nodesById[edgeData.target].shape !== 'label';
-
- return {
- id: edgeData.id,
- type: 'default',
- source: edgeData.source,
- sourceHandle: isInside ? 'inside' : isOutside ? 'outside' : undefined,
- target: edgeData.target,
- targetHandle: isIn ? 'in' : isOut ? 'out' : undefined,
- data: { ...edgeData },
- };
- });
-
- return { initialNodes, initialEdges };
-}
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/index.ts b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/index.ts
index 1fec1c76430eb..5b2f8d71323bb 100644
--- a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/index.ts
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/index.ts
@@ -4,3 +4,14 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
+
+export { Graph } from './graph/graph';
+export type { GraphProps } from './graph/graph';
+export type {
+ NodeViewModel,
+ EdgeViewModel,
+ GroupNodeViewModel,
+ LabelNodeViewModel,
+ EntityNodeViewModel,
+ NodeProps,
+} from './types';
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/mock/react_flow.ts b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/mock/react_flow.ts
new file mode 100644
index 0000000000000..35282dedcc6de
--- /dev/null
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/mock/react_flow.ts
@@ -0,0 +1,69 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+/* eslint-disable max-classes-per-file */
+
+// Copied from https://reactflow.dev/learn/advanced-use/testing#using-jest
+
+// To make sure that the tests are working, it's important that you are using
+// this implementation of ResizeObserver and DOMMatrixReadOnly
+class ResizeObserver {
+ callback: globalThis.ResizeObserverCallback;
+
+ constructor(callback: globalThis.ResizeObserverCallback) {
+ this.callback = callback;
+ }
+
+ observe(target: Element) {
+ this.callback([{ target } as globalThis.ResizeObserverEntry], this);
+ }
+
+ unobserve() {}
+
+ disconnect() {}
+}
+
+class DOMMatrixReadOnly {
+ m22: number;
+ constructor(transform: string) {
+ const scale = transform?.match(/scale\(([1-9.])\)/)?.[1];
+ this.m22 = scale !== undefined ? +scale : 1;
+ }
+}
+
+// Only run the shim once when requested
+let init = false;
+
+export const mockReactFlow = () => {
+ if (init) return;
+ init = true;
+
+ global.ResizeObserver = ResizeObserver;
+
+ // @ts-ignore
+ global.DOMMatrixReadOnly = DOMMatrixReadOnly;
+
+ Object.defineProperties(global.HTMLElement.prototype, {
+ offsetHeight: {
+ get() {
+ return parseFloat(this.style.height) || 1;
+ },
+ },
+ offsetWidth: {
+ get() {
+ return parseFloat(this.style.width) || 1;
+ },
+ },
+ });
+
+ (global.SVGElement as any).prototype.getBBox = () => ({
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0,
+ });
+};
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/mock/test_providers.tsx b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/mock/test_providers.tsx
new file mode 100644
index 0000000000000..3d07c1c6037ed
--- /dev/null
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/mock/test_providers.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 from 'react';
+import { euiDarkVars } from '@kbn/ui-theme';
+import { ThemeProvider } from '@emotion/react';
+
+interface Props {
+ children?: React.ReactNode;
+}
+
+/** A utility for wrapping children in the providers required to run most tests */
+export const TestProvidersComponent: React.FC = ({ children }) => {
+ return (
+ ({ eui: euiDarkVars, darkMode: true })}>{children}
+ );
+};
+
+export const TestProviders = React.memo(TestProvidersComponent);
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/button.stories.tsx b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/button.stories.tsx
index 5e6e4cd37b432..4a034c05ee166 100644
--- a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/button.stories.tsx
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/button.stories.tsx
@@ -8,7 +8,7 @@
import React from 'react';
import { ThemeProvider } from '@emotion/react';
import { Story } from '@storybook/react';
-import { NodeButton, type NodeButtonProps, NodeContainer } from './styles';
+import { NodeButton, type NodeButtonProps, NodeShapeContainer } from './styles';
export default {
title: 'Components/Graph Components',
@@ -20,10 +20,10 @@ export default {
const Template: Story = (args) => (
-
+
Hover me
-
+
);
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/diamond_node.tsx b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/diamond_node.tsx
index 76e7a3cd9eeeb..f96068061a433 100644
--- a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/diamond_node.tsx
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/diamond_node.tsx
@@ -10,7 +10,7 @@ import { useEuiBackgroundColor, useEuiTheme } from '@elastic/eui';
import { Handle, Position } from '@xyflow/react';
import type { EntityNodeViewModel, NodeProps } from '../types';
import {
- NodeContainer,
+ NodeShapeContainer,
NodeLabel,
NodeShapeOnHoverSvg,
NodeShapeSvg,
@@ -18,6 +18,7 @@ import {
NodeButton,
HandleStyleOverride,
} from './styles';
+import { DiamondHoverShape, DiamondShape } from './shapes/diamond_shape';
const NODE_WIDTH = 99;
const NODE_HEIGHT = 98;
@@ -27,59 +28,55 @@ export const DiamondNode: React.FC = memo((props: NodeProps) => {
props.data as EntityNodeViewModel;
const { euiTheme } = useEuiTheme();
return (
-
- {interactive && (
-
+
+ {interactive && (
+
+
+
+ )}
+
-
-
- )}
-
- }
+
+ {interactive && (
+ expandButtonClick?.(e, props)}
+ x={`${NODE_WIDTH - NodeButton.ExpandButtonSize}px`}
+ y={`${(NODE_HEIGHT - NodeButton.ExpandButtonSize) / 2 - 4}px`}
+ />
+ )}
+
- {icon && }
-
- {interactive && (
- expandButtonClick?.(e, props)}
- x={`${NODE_WIDTH - NodeButton.ExpandButtonSize}px`}
- y={`${(NODE_HEIGHT - NodeButton.ExpandButtonSize) / 2 - 4}px`}
+
- )}
-
-
+
{Boolean(label) ? label : id}
-
+ >
);
});
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/ellipse_node.tsx b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/ellipse_node.tsx
index 3359905196b9d..987b9d7577812 100644
--- a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/ellipse_node.tsx
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/ellipse_node.tsx
@@ -9,7 +9,7 @@ import React, { memo } from 'react';
import { useEuiBackgroundColor, useEuiTheme } from '@elastic/eui';
import { Handle, Position } from '@xyflow/react';
import {
- NodeContainer,
+ NodeShapeContainer,
NodeLabel,
NodeShapeOnHoverSvg,
NodeShapeSvg,
@@ -18,6 +18,7 @@ import {
HandleStyleOverride,
} from './styles';
import type { EntityNodeViewModel, NodeProps } from '../types';
+import { EllipseHoverShape, EllipseShape } from './shapes/ellipse_shape';
const NODE_WIDTH = 90;
const NODE_HEIGHT = 90;
@@ -27,63 +28,55 @@ export const EllipseNode: React.FC = memo((props: NodeProps) => {
props.data as EntityNodeViewModel;
const { euiTheme } = useEuiTheme();
return (
-
- {interactive && (
-
+
+ {interactive && (
+
+
+
+ )}
+
-
-
- )}
-
- }
+
+ {interactive && (
+ expandButtonClick?.(e, props)}
+ x={`${NODE_WIDTH - NodeButton.ExpandButtonSize / 2}px`}
+ y={`${(NODE_HEIGHT - NodeButton.ExpandButtonSize) / 2}px`}
+ />
+ )}
+
- {icon && }
-
- {interactive && (
- expandButtonClick?.(e, props)}
- x={`${NODE_WIDTH - NodeButton.ExpandButtonSize / 2}px`}
- y={`${(NODE_HEIGHT - NodeButton.ExpandButtonSize) / 2}px`}
+
- )}
-
-
+
{Boolean(label) ? label : id}
-
+ >
);
});
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/hexagon_node.tsx b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/hexagon_node.tsx
index dee8df697c844..0bd8c33fc6484 100644
--- a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/hexagon_node.tsx
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/hexagon_node.tsx
@@ -9,7 +9,7 @@ import React, { memo } from 'react';
import { useEuiBackgroundColor, useEuiTheme } from '@elastic/eui';
import { Handle, Position } from '@xyflow/react';
import {
- NodeContainer,
+ NodeShapeContainer,
NodeLabel,
NodeShapeOnHoverSvg,
NodeShapeSvg,
@@ -18,6 +18,7 @@ import {
HandleStyleOverride,
} from './styles';
import type { EntityNodeViewModel, NodeProps } from '../types';
+import { HexagonHoverShape, HexagonShape } from './shapes/hexagon_shape';
const NODE_WIDTH = 87;
const NODE_HEIGHT = 96;
@@ -27,59 +28,55 @@ export const HexagonNode: React.FC = memo((props: NodeProps) => {
props.data as EntityNodeViewModel;
const { euiTheme } = useEuiTheme();
return (
-
- {interactive && (
-
+
+ {interactive && (
+
+
+
+ )}
+
-
-
- )}
-
- }
+
+ {interactive && (
+ expandButtonClick?.(e, props)}
+ x={`${NODE_WIDTH - NodeButton.ExpandButtonSize / 2 + 2}px`}
+ y={`${(NODE_HEIGHT - NodeButton.ExpandButtonSize) / 2 - 2}px`}
+ />
+ )}
+
- {icon && }
-
- {interactive && (
- expandButtonClick?.(e, props)}
- x={`${NODE_WIDTH - NodeButton.ExpandButtonSize / 2 + 2}px`}
- y={`${(NODE_HEIGHT - NodeButton.ExpandButtonSize) / 2 - 2}px`}
+
- )}
-
-
+
{Boolean(label) ? label : id}
-
+ >
);
});
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/pentagon_node.tsx b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/pentagon_node.tsx
index 74ea8c05b5940..f2282e9fa2d7d 100644
--- a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/pentagon_node.tsx
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/pentagon_node.tsx
@@ -10,7 +10,7 @@ import { useEuiBackgroundColor, useEuiTheme } from '@elastic/eui';
import styled from '@emotion/styled';
import { Handle, Position } from '@xyflow/react';
import {
- NodeContainer,
+ NodeShapeContainer,
NodeLabel,
NodeShapeOnHoverSvg,
NodeShapeSvg,
@@ -19,6 +19,7 @@ import {
HandleStyleOverride,
} from './styles';
import type { EntityNodeViewModel, NodeProps } from '../types';
+import { PentagonHoverShape, PentagonShape } from './shapes/pentagon_shape';
const PentagonShapeOnHover = styled(NodeShapeOnHoverSvg)`
transform: translate(-50%, -51.5%);
@@ -32,59 +33,55 @@ export const PentagonNode: React.FC = memo((props: NodeProps) => {
props.data as EntityNodeViewModel;
const { euiTheme } = useEuiTheme();
return (
-
- {interactive && (
-
+
+ {interactive && (
+
+
+
+ )}
+
-
-
- )}
-
- }
+
+ {interactive && (
+ expandButtonClick?.(e, props)}
+ x={`${NODE_WIDTH - NodeButton.ExpandButtonSize / 2}px`}
+ y={`${(NODE_HEIGHT - NodeButton.ExpandButtonSize) / 2}px`}
+ />
+ )}
+
- {icon && }
-
- {interactive && (
- expandButtonClick?.(e, props)}
- x={`${NODE_WIDTH - NodeButton.ExpandButtonSize / 2}px`}
- y={`${(NODE_HEIGHT - NodeButton.ExpandButtonSize) / 2}px`}
+
- )}
-
-
+
{Boolean(label) ? label : id}
-
+ >
);
});
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/rectangle_node.tsx b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/rectangle_node.tsx
index 22d9fbf25a4eb..7a5fc14855bc9 100644
--- a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/rectangle_node.tsx
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/rectangle_node.tsx
@@ -9,7 +9,7 @@ import React, { memo } from 'react';
import { useEuiBackgroundColor, useEuiTheme } from '@elastic/eui';
import { Handle, Position } from '@xyflow/react';
import {
- NodeContainer,
+ NodeShapeContainer,
NodeLabel,
NodeShapeOnHoverSvg,
NodeShapeSvg,
@@ -18,6 +18,7 @@ import {
HandleStyleOverride,
} from './styles';
import type { EntityNodeViewModel, NodeProps } from '../types';
+import { RectangleHoverShape, RectangleShape } from './shapes/rectangle_shape';
const NODE_WIDTH = 81;
const NODE_HEIGHT = 80;
@@ -27,67 +28,55 @@ export const RectangleNode: React.FC = memo((props: NodeProps) => {
props.data as EntityNodeViewModel;
const { euiTheme } = useEuiTheme();
return (
-
- {interactive && (
-
+
+ {interactive && (
+
+
+
+ )}
+
-
-
- )}
-
- }
+
+ {interactive && (
+ expandButtonClick?.(e, props)}
+ x={`${NODE_WIDTH - NodeButton.ExpandButtonSize / 4}px`}
+ y={`${(NODE_HEIGHT - NodeButton.ExpandButtonSize / 2) / 2}px`}
+ />
+ )}
+
- {icon && }
-
- {interactive && (
- expandButtonClick?.(e, props)}
- x={`${NODE_WIDTH - NodeButton.ExpandButtonSize / 4}px`}
- y={`${(NODE_HEIGHT - NodeButton.ExpandButtonSize / 2) / 2}px`}
+
- )}
-
-
+
{Boolean(label) ? label : id}
-
+ >
);
});
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/diamond_shape.tsx b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/diamond_shape.tsx
new file mode 100644
index 0000000000000..126a5702cf5d0
--- /dev/null
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/diamond_shape.tsx
@@ -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 React, { memo } from 'react';
+import type { HoverShapeProps, ShapeProps } from './types';
+
+export const DiamondHoverShape: React.FC = memo(({ stroke }) => (
+
+));
+
+export const DiamondShape: React.FC = memo(({ stroke, fill }) => (
+
+));
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/ellipse_shape.tsx b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/ellipse_shape.tsx
new file mode 100644
index 0000000000000..18fe56440c5f5
--- /dev/null
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/ellipse_shape.tsx
@@ -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 React, { memo } from 'react';
+import type { HoverShapeProps, ShapeProps } from './types';
+
+export const EllipseHoverShape: React.FC = memo(({ stroke }) => (
+
+));
+
+export const EllipseShape: React.FC = memo(({ stroke, fill }) => (
+
+));
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/hexagon_shape.tsx b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/hexagon_shape.tsx
new file mode 100644
index 0000000000000..12aeebec88605
--- /dev/null
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/hexagon_shape.tsx
@@ -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 React, { memo } from 'react';
+import type { HoverShapeProps, ShapeProps } from './types';
+
+export const HexagonHoverShape: React.FC = memo(({ stroke }) => (
+
+));
+
+export const HexagonShape: React.FC = memo(({ stroke, fill }) => (
+
+));
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/pentagon_shape.tsx b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/pentagon_shape.tsx
new file mode 100644
index 0000000000000..f4d07fc69db79
--- /dev/null
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/pentagon_shape.tsx
@@ -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 React, { memo } from 'react';
+import type { HoverShapeProps, ShapeProps } from './types';
+
+export const PentagonHoverShape: React.FC = memo(({ stroke }) => (
+
+));
+
+export const PentagonShape: React.FC = memo(({ stroke, fill }) => (
+
+));
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/rectangle_shape.tsx b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/rectangle_shape.tsx
new file mode 100644
index 0000000000000..7d019ce331baf
--- /dev/null
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/rectangle_shape.tsx
@@ -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 React, { memo } from 'react';
+import type { HoverShapeProps, ShapeProps } from './types';
+
+export const RectangleHoverShape: React.FC = memo(({ stroke }) => (
+
+));
+
+export const RectangleShape: React.FC = memo(({ stroke, fill }) => (
+
+));
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/types.ts b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/types.ts
new file mode 100644
index 0000000000000..0f6910258fed6
--- /dev/null
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/shapes/types.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.
+ */
+
+export interface HoverShapeProps {
+ stroke: string;
+}
+
+export interface ShapeProps {
+ stroke: string;
+ fill: string;
+}
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/styles.tsx b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/styles.tsx
index f1bee0cf95e30..e76da737af0f9 100644
--- a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/styles.tsx
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/node/styles.tsx
@@ -23,6 +23,7 @@ export const LABEL_PADDING_X = 15;
export const LABEL_BORDER_WIDTH = 1;
export const NODE_WIDTH = 90;
export const NODE_HEIGHT = 90;
+const NODE_LABEL_WIDTH = 120;
export const LabelNodeContainer = styled.div`
text-wrap: nowrap;
@@ -79,9 +80,13 @@ export const LabelShapeOnHover = styled.div`
${LabelNodeContainer}:hover & {
opacity: 1; /* Show on hover */
}
+
+ .react-flow__node:focus:focus-visible & {
+ opacity: 1; /* Show on hover */
+ }
`;
-export const NodeContainer = styled.div`
+export const NodeShapeContainer = styled.div`
position: relative;
width: ${NODE_WIDTH}px;
height: ${NODE_HEIGHT}px;
@@ -99,7 +104,11 @@ export const NodeShapeOnHoverSvg = styled(NodeShapeSvg)`
opacity: 0; /* Hidden by default */
transition: opacity 0.2s ease; /* Smooth transition */
- ${NodeContainer}:hover & {
+ ${NodeShapeContainer}:hover & {
+ opacity: 1; /* Show on hover */
+ }
+
+ .react-flow__node:focus:focus-visible & {
opacity: 1; /* Show on hover */
}
`;
@@ -124,11 +133,8 @@ export const NodeIcon = ({ icon, color, x, y }: NodeIconProps) => {
};
export const NodeLabel = styled(EuiText)`
- position: absolute;
- top: 108%;
- left: 50%;
- transform: translateX(-50%);
- width: 130%;
+ width: ${NODE_LABEL_WIDTH}px;
+ margin-left: ${-(NODE_LABEL_WIDTH - NODE_WIDTH) / 2}px;
text-overflow: ellipsis;
// white-space: nowrap;
overflow: hidden;
@@ -167,9 +173,17 @@ export const StyledNodeButton = styled.div`
position: absolute;
z-index: 1;
- ${NodeContainer}:hover & {
+ ${NodeShapeContainer}:hover & {
opacity: 1; /* Show on hover */
}
+
+ &:has(button:focus) {
+ opacity: 1; /* Show when button is active */
+ }
+
+ .react-flow__node:focus:focus-visible & {
+ opacity: 1; /* Show on node focus */
+ }
`;
export interface NodeButtonProps {
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/types.ts b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/types.ts
index 262254c80afe3..27ec18f35f45b 100644
--- a/x-pack/packages/kbn-cloud-security-posture/graph/src/components/types.ts
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/src/components/types.ts
@@ -10,29 +10,17 @@ import type {
GroupNodeDataModel,
LabelNodeDataModel,
EdgeDataModel,
+ NodeShape,
} from '@kbn/cloud-security-posture-common/types/graph/latest';
import type { Node, NodeProps as xyNodeProps } from '@xyflow/react';
import type { Edge, EdgeProps as xyEdgeProps } from '@xyflow/react';
-export interface PositionXY {
- x: number;
- y: number;
-}
-
export interface Size {
width: number;
height: number;
}
-export interface GraphMetadata {
- nodes: { [key: string]: { edgesIn: number; edgesOut: number } };
- edges: {
- [key: string]: { source: string; target: string; edgesStacked: number; edges: string[] };
- };
-}
-
interface BaseNodeDataViewModel {
- position: PositionXY;
interactive?: boolean;
}
@@ -46,9 +34,7 @@ export interface EntityNodeViewModel
export interface GroupNodeViewModel
extends Record,
GroupNodeDataModel,
- BaseNodeDataViewModel {
- size?: Size;
-}
+ BaseNodeDataViewModel {}
export interface LabelNodeViewModel
extends Record,
@@ -61,10 +47,13 @@ export type NodeViewModel = EntityNodeViewModel | GroupNodeViewModel | LabelNode
export type NodeProps = xyNodeProps>;
-export interface EdgeViewModel extends Record, EdgeDataModel {
- graphMetadata?: GraphMetadata;
- interactive?: boolean;
- onClick?: (e: React.MouseEvent, edge: EdgeProps) => void;
-}
+export interface EdgeViewModel extends Record, EdgeDataModel {}
-export type EdgeProps = xyEdgeProps>;
+export type EdgeProps = xyEdgeProps<
+ Edge<
+ EdgeViewModel & {
+ sourceShape: NodeShape;
+ targetShape: NodeShape;
+ }
+ >
+>;
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/storybook/config/main.ts b/x-pack/packages/kbn-cloud-security-posture/graph/storybook/config/main.ts
deleted file mode 100644
index 186e1a2a76bed..0000000000000
--- a/x-pack/packages/kbn-cloud-security-posture/graph/storybook/config/main.ts
+++ /dev/null
@@ -1,44 +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 { defaultConfig } from '@kbn/storybook';
-import { Configuration } from 'webpack';
-
-module.exports = {
- ...defaultConfig,
- stories: ['../../**/*.stories.+(tsx|mdx)'],
- reactOptions: {
- strictMode: true,
- },
- webpack: (config: Configuration) => {
- config.module?.rules.push({
- test: /\.js$/,
- include: /node_modules[\\\/]@dagrejs/,
- use: {
- loader: 'babel-loader',
- options: {
- presets: ['@babel/preset-env'],
- plugins: ['@babel/plugin-proposal-class-properties'],
- },
- },
- });
- config.module?.rules.push({
- test: /node_modules[\/\\]@?xyflow[\/\\].*.js$/,
- loaders: 'babel-loader',
- options: {
- presets: [['@babel/preset-env', { modules: false }], '@babel/preset-react'],
- plugins: [
- '@babel/plugin-proposal-optional-chaining',
- '@babel/plugin-proposal-nullish-coalescing-operator',
- '@babel/plugin-transform-logical-assignment-operators',
- ],
- },
- });
-
- return config;
- },
-};
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/tsconfig.json b/x-pack/packages/kbn-cloud-security-posture/graph/tsconfig.json
index d97809a59772d..d0056e29e6784 100644
--- a/x-pack/packages/kbn-cloud-security-posture/graph/tsconfig.json
+++ b/x-pack/packages/kbn-cloud-security-posture/graph/tsconfig.json
@@ -13,6 +13,6 @@
"kbn_references": [
"@kbn/cloud-security-posture-common",
"@kbn/utility-types",
- "@kbn/storybook"
+ "@kbn/ui-theme",
]
}
diff --git a/x-pack/packages/kbn-cloud-security-posture/public/kibana.jsonc b/x-pack/packages/kbn-cloud-security-posture/public/kibana.jsonc
index 4c5a4f1f0165d..811a1ab5dad41 100644
--- a/x-pack/packages/kbn-cloud-security-posture/public/kibana.jsonc
+++ b/x-pack/packages/kbn-cloud-security-posture/public/kibana.jsonc
@@ -1,5 +1,5 @@
{
- "id": "@kbn/cloud-security-posture",
- "owner": "@elastic/kibana-cloud-security-posture",
- "type": "shared-browser"
-}
\ No newline at end of file
+ "id": "@kbn/cloud-security-posture",
+ "owner": "@elastic/kibana-cloud-security-posture",
+ "type": "shared-browser"
+}
diff --git a/x-pack/packages/kbn-cloud-security-posture/storybook/config/README.mdx b/x-pack/packages/kbn-cloud-security-posture/storybook/config/README.mdx
new file mode 100644
index 0000000000000..ab9ce5263ec69
--- /dev/null
+++ b/x-pack/packages/kbn-cloud-security-posture/storybook/config/README.mdx
@@ -0,0 +1,3 @@
+# @kbn/cloud-security-posture-storybook-config
+
+Storybook configuration used by `yarn storybook`. Refer to `@kbn/storybook` for more information.
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/storybook/config/constants.ts b/x-pack/packages/kbn-cloud-security-posture/storybook/config/constants.ts
similarity index 100%
rename from x-pack/packages/kbn-cloud-security-posture/graph/storybook/config/constants.ts
rename to x-pack/packages/kbn-cloud-security-posture/storybook/config/constants.ts
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/storybook/config/index.ts b/x-pack/packages/kbn-cloud-security-posture/storybook/config/index.ts
similarity index 100%
rename from x-pack/packages/kbn-cloud-security-posture/graph/storybook/config/index.ts
rename to x-pack/packages/kbn-cloud-security-posture/storybook/config/index.ts
diff --git a/x-pack/packages/kbn-cloud-security-posture/storybook/config/main.ts b/x-pack/packages/kbn-cloud-security-posture/storybook/config/main.ts
new file mode 100644
index 0000000000000..4e7fca030c2f6
--- /dev/null
+++ b/x-pack/packages/kbn-cloud-security-posture/storybook/config/main.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 { defaultConfig } from '@kbn/storybook';
+
+module.exports = {
+ ...defaultConfig,
+ stories: ['../../**/*.stories.+(tsx|mdx)'],
+ reactOptions: {
+ strictMode: true,
+ },
+};
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/storybook/config/manager.ts b/x-pack/packages/kbn-cloud-security-posture/storybook/config/manager.ts
similarity index 100%
rename from x-pack/packages/kbn-cloud-security-posture/graph/storybook/config/manager.ts
rename to x-pack/packages/kbn-cloud-security-posture/storybook/config/manager.ts
diff --git a/x-pack/packages/kbn-cloud-security-posture/storybook/config/package.json b/x-pack/packages/kbn-cloud-security-posture/storybook/config/package.json
new file mode 100644
index 0000000000000..4ba8c8fd3d57f
--- /dev/null
+++ b/x-pack/packages/kbn-cloud-security-posture/storybook/config/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "@kbn/cloud-security-posture-storybook-config",
+ "private": true,
+ "version": "1.0.0",
+ "license": "Elastic License 2.0"
+}
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/storybook/config/preview.ts b/x-pack/packages/kbn-cloud-security-posture/storybook/config/preview.ts
similarity index 100%
rename from x-pack/packages/kbn-cloud-security-posture/graph/storybook/config/preview.ts
rename to x-pack/packages/kbn-cloud-security-posture/storybook/config/preview.ts
diff --git a/x-pack/packages/kbn-cloud-security-posture/graph/storybook/config/styles.css b/x-pack/packages/kbn-cloud-security-posture/storybook/config/styles.css
similarity index 100%
rename from x-pack/packages/kbn-cloud-security-posture/graph/storybook/config/styles.css
rename to x-pack/packages/kbn-cloud-security-posture/storybook/config/styles.css
diff --git a/x-pack/packages/kbn-cloud-security-posture/storybook/config/tsconfig.json b/x-pack/packages/kbn-cloud-security-posture/storybook/config/tsconfig.json
new file mode 100644
index 0000000000000..1f8b2275f5191
--- /dev/null
+++ b/x-pack/packages/kbn-cloud-security-posture/storybook/config/tsconfig.json
@@ -0,0 +1,20 @@
+{
+ "extends": "../../../../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "target/types",
+ "types": [
+ "jest",
+ "node",
+ "@kbn/ambient-storybook-types",
+ ]
+ },
+ "include": [
+ "**/*.ts"
+ ],
+ "kbn_references": [
+ "@kbn/storybook",
+ ],
+ "exclude": [
+ "target/**/*",
+ ]
+}
diff --git a/x-pack/packages/security-solution/common/src/flyout/common/components/expandable_panel.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/expandable_panel.tsx
index 4f1890e58554f..383bbbb341c8e 100644
--- a/x-pack/packages/security-solution/common/src/flyout/common/components/expandable_panel.tsx
+++ b/x-pack/packages/security-solution/common/src/flyout/common/components/expandable_panel.tsx
@@ -22,7 +22,7 @@ import {
EuiSkeletonText,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import type { IconType } from '@elastic/eui';
+import type { EuiPanelProps, IconType } from '@elastic/eui';
import { css } from '@emotion/react';
export interface ExpandablePanelPanelProps {
@@ -59,6 +59,10 @@ export interface ExpandablePanelPanelProps {
* Returns a null component if true
*/
error?: boolean;
+ /**
+ * Content's padding size
+ */
+ paddingSize?: EuiPanelProps['paddingSize'];
};
expand?: {
/**
@@ -84,7 +88,11 @@ export interface ExpandablePanelPanelProps {
*/
export const ExpandablePanel: FC> = ({
header: { title, link, iconType, headerContent },
- content: { loading, error } = { loading: false, error: false },
+ content: { loading, error, paddingSize: contentPaddingSize } = {
+ loading: false,
+ error: false,
+ paddingSize: 'm',
+ },
expand: { expandable, expandedOnFirstRender } = {
expandable: false,
expandedOnFirstRender: false,
@@ -228,7 +236,9 @@ export const ExpandablePanel: FC> =
{showContent && (
- {content}
+
+ {content}
+
)}
diff --git a/x-pack/plugins/cloud_security_posture/server/routes/graph/v1.ts b/x-pack/plugins/cloud_security_posture/server/routes/graph/v1.ts
index eb372a2bfea4f..5102d153c1905 100644
--- a/x-pack/plugins/cloud_security_posture/server/routes/graph/v1.ts
+++ b/x-pack/plugins/cloud_security_posture/server/routes/graph/v1.ts
@@ -6,6 +6,7 @@
*/
import { castArray } from 'lodash';
+import { v4 as uuidv4 } from 'uuid';
import type { Logger, IScopedClusterClient } from '@kbn/core/server';
import type {
EdgeDataModel,
@@ -13,10 +14,9 @@ import type {
EntityNodeDataModel,
LabelNodeDataModel,
GroupNodeDataModel,
- NodeShape,
} from '@kbn/cloud-security-posture-common/types/graph/latest';
import type { EsqlToRecords } from '@elastic/elasticsearch/lib/helpers';
-import type { Writeable } from '@kbn/zod';
+import type { Writable } from '@kbn/utility-types';
import type { GraphContextServices, GraphContext } from './types';
interface GraphEdge {
@@ -31,6 +31,11 @@ interface GraphEdge {
isAlert: boolean;
}
+interface LabelEdges {
+ source: string;
+ target: string;
+}
+
export const getGraph = async (
services: GraphContextServices,
query: {
@@ -63,28 +68,29 @@ export const getGraph = async (
interface ParseContext {
nodesMap: Record;
- edgeLabelsNodes: Record;
edgesMap: Record;
+ edgeLabelsNodes: Record;
+ labelEdges: Record;
}
const parseRecords = (logger: Logger, records: GraphEdge[]): GraphContext => {
- const nodesMap: Record = {};
- const edgeLabelsNodes: Record = {};
- const edgesMap: Record = {};
+ const ctx: ParseContext = { nodesMap: {}, edgeLabelsNodes: {}, edgesMap: {}, labelEdges: {} };
logger.trace(`Parsing records [length: ${records.length}]`);
- createNodes(logger, records, { nodesMap, edgeLabelsNodes });
- createEdgesAndGroups(logger, { edgeLabelsNodes, edgesMap, nodesMap });
+ createNodes(logger, records, ctx);
+ createEdgesAndGroups(logger, ctx);
logger.trace(
- `Parsed [nodes: ${Object.keys(nodesMap).length}, edges: ${Object.keys(edgesMap).length}]`
+ `Parsed [nodes: ${Object.keys(ctx.nodesMap).length}, edges: ${
+ Object.keys(ctx.edgesMap).length
+ }]`
);
// Sort groups to be first (fixes minor layout issue)
- const nodes = sortNodes(nodesMap);
+ const nodes = sortNodes(ctx.nodesMap);
- return { nodes, edges: Object.values(edgesMap) };
+ return { nodes, edges: Object.values(ctx.edgesMap) };
};
const fetchGraph = async ({
@@ -168,12 +174,21 @@ const createNodes = (
records: GraphEdge[],
context: Omit
) => {
- const { nodesMap, edgeLabelsNodes } = context;
+ const { nodesMap, edgeLabelsNodes, labelEdges } = context;
for (const record of records) {
const { ips, hosts, users, actorIds, action, targetIds, isAlert, eventOutcome } = record;
const actorIdsArray = castArray(actorIds);
const targetIdsArray = castArray(targetIds);
+ const unknownTargets: string[] = [];
+
+ // Ensure all targets has an id (target can return null from the query)
+ targetIdsArray.forEach((id, idx) => {
+ if (!id) {
+ targetIdsArray[idx] = `unknown ${uuidv4()}`;
+ unknownTargets.push(targetIdsArray[idx]);
+ }
+ });
logger.trace(
`Parsing record [actorIds: ${actorIdsArray.join(
@@ -186,7 +201,7 @@ const createNodes = (
if (nodesMap[id] === undefined) {
nodesMap[id] = {
id,
- label: id,
+ label: unknownTargets.includes(id) ? 'Unknown' : undefined,
color: isAlert ? 'danger' : 'primary',
...determineEntityNodeShape(id, ips ?? [], hosts ?? [], users ?? []),
};
@@ -204,19 +219,18 @@ const createNodes = (
edgeLabelsNodes[edgeId] = [];
}
- const labelNode = {
+ const labelNode: LabelNodeDataModel = {
id: edgeId + `label(${action})outcome(${eventOutcome})`,
label: action,
- source: actorId,
- target: targetId,
color: isAlert ? 'danger' : eventOutcome === 'failed' ? 'warning' : 'primary',
shape: 'label',
- } as LabelNodeDataModel;
+ };
logger.trace(`Creating label node [${labelNode.id}]`);
nodesMap[labelNode.id] = labelNode;
edgeLabelsNodes[edgeId].push(labelNode.id);
+ labelEdges[labelNode.id] = { source: actorId, target: targetId };
}
}
}
@@ -265,7 +279,7 @@ const sortNodes = (nodesMap: Record) => {
};
const createEdgesAndGroups = (logger: Logger, context: ParseContext) => {
- const { edgeLabelsNodes, edgesMap, nodesMap } = context;
+ const { edgeLabelsNodes, edgesMap, nodesMap, labelEdges } = context;
Object.entries(edgeLabelsNodes).forEach(([edgeId, edgeLabelsIds]) => {
// When there's more than one edge label, create a group node
@@ -276,9 +290,9 @@ const createEdgesAndGroups = (logger: Logger, context: ParseContext) => {
logger,
edgesMap,
nodesMap,
- (nodesMap[edgeLabelId] as LabelNodeDataModel).source,
+ labelEdges[edgeLabelId].source,
edgeLabelId,
- (nodesMap[edgeLabelId] as LabelNodeDataModel).target
+ labelEdges[edgeLabelId].target
);
} else {
const groupNode: GroupNodeDataModel = {
@@ -291,13 +305,13 @@ const createEdgesAndGroups = (logger: Logger, context: ParseContext) => {
logger,
edgesMap,
nodesMap,
- (nodesMap[edgeLabelsIds[0]] as LabelNodeDataModel).source,
+ labelEdges[edgeLabelsIds[0]].source,
groupNode.id,
- (nodesMap[edgeLabelsIds[0]] as LabelNodeDataModel).target
+ labelEdges[edgeLabelsIds[0]].target
);
edgeLabelsIds.forEach((edgeLabelId) => {
- (nodesMap[edgeLabelId] as Writeable).parentId = groupNode.id;
+ (nodesMap[edgeLabelId] as Writable).parentId = groupNode.id;
connectEntitiesAndLabelNode(
logger,
edgesMap,
@@ -332,7 +346,7 @@ const connectNodes = (
nodesMap: Record,
sourceNodeId: string,
targetNodeId: string
-) => {
+): EdgeDataModel => {
const sourceNode = nodesMap[sourceNodeId];
const targetNode = nodesMap[targetNodeId];
const color =
@@ -345,9 +359,7 @@ const connectNodes = (
return {
id: `a(${sourceNodeId})-b(${targetNodeId})`,
source: sourceNodeId,
- sourceShape: nodesMap[sourceNodeId].shape as NodeShape,
target: targetNodeId,
- targetShape: nodesMap[targetNodeId].shape as NodeShape,
color,
- } as EdgeDataModel;
+ };
};
diff --git a/x-pack/plugins/cloud_security_posture/tsconfig.json b/x-pack/plugins/cloud_security_posture/tsconfig.json
index 456035c9112d1..f3883e0fc43c6 100755
--- a/x-pack/plugins/cloud_security_posture/tsconfig.json
+++ b/x-pack/plugins/cloud_security_posture/tsconfig.json
@@ -66,7 +66,6 @@
"@kbn/cloud-security-posture-common",
"@kbn/cloud-security-posture",
"@kbn/analytics",
- "@kbn/zod"
],
"exclude": ["target/**/*"]
}
diff --git a/x-pack/plugins/fleet/README.md b/x-pack/plugins/fleet/README.md
index fe61ca1d7cc51..d033e857b5ebd 100644
--- a/x-pack/plugins/fleet/README.md
+++ b/x-pack/plugins/fleet/README.md
@@ -32,6 +32,7 @@ In addition, it is typically needed to set up a Fleet Server and enroll Elastic
- [Running a local Fleet Server and enrolling Elastic Agents](dev_docs/local_setup/enrolling_agents.md) for developing Kibana in stateful (not serverless) mode
- [Developing Kibana in serverless mode](dev_docs/local_setup/developing_kibana_in_serverless.md) for developing Kibana in serverless mode
- [Developing Kibana and Fleet Server simultaneously](dev_docs/local_setup/developing_kibana_and_fleet_server.md) for doing simultaneous Kibana and Fleet Server development
+- [Testing agentless integrations](dev_docs/local_setup/agentless.md)
### Running Fleet locally in stateful mode
diff --git a/x-pack/plugins/fleet/dev_docs/local_setup/agentless.md b/x-pack/plugins/fleet/dev_docs/local_setup/agentless.md
new file mode 100644
index 0000000000000..a6f62a29a7179
--- /dev/null
+++ b/x-pack/plugins/fleet/dev_docs/local_setup/agentless.md
@@ -0,0 +1,28 @@
+# Testing agentless integrations
+
+Integrations have two possible deployment modes:
+* on user-managed agents (most cases)
+* on internally managed agents: these are called agentless
+
+## Kibana config
+
+Agentless integrations are available in ESS and Serverless, so in order to test or develop these in a local environment, the config should emulate either of these.
+
+At the time of writing, this can be achieved by adding the following to your `kibana.dev.yml`:
+```
+# Emulate cloud
+xpack.cloud.id: "123456789"
+
+# Enable agentless experimental feature flag in Fleet
+xpack.fleet.enableExperimental: ['agentless']
+# Agentless Fleet config
+xpack.fleet.agentless.enabled: true
+xpack.fleet.agentless.api.url: 'https://api.agentless.url/api/v1/ess'
+xpack.fleet.agentless.api.tls.certificate: './config/node.crt'
+xpack.fleet.agentless.api.tls.key: './config/node.key'
+xpack.fleet.agentless.api.tls.ca: './config/ca.crt'
+```
+
+## Which integrations to test with?
+
+At the time of writing, the Elastic Connectors integration is [agentless only](https://github.com/elastic/integrations/blob/2ebdf0cada6faed352e71a82cf71487672f27bf2/packages/elastic_connectors/manifest.yml#L35-L39) and the Cloud Security Posture Management (CSPM) integration offers both agent-based and agentless deployment modes. These are still in technical preview, so "Display beta integrations" should be checked.
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts
index 38663d88e5b23..bd57576a4cafa 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts
@@ -227,6 +227,74 @@ describe('useSetupTechnology', () => {
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED);
});
+ it('should set the default selected setup technology to agent-based when creating a non agentless-only package policy', 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,
+ packageInfo: packageInfoMock,
+ packagePolicy: packagePolicyMock,
+ })
+ );
+
+ expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED);
+ });
+
+ it('should set the default selected setup technology to agentless when creating an agentless-only package policy', async () => {
+ (useConfig as MockFn).mockReturnValue({
+ agentless: {
+ enabled: true,
+ api: {
+ url: 'https://agentless.api.url',
+ },
+ },
+ } as any);
+ (useStartServices as MockFn).mockReturnValue({
+ cloud: {
+ isCloudEnabled: true,
+ },
+ });
+ const agentlessOnlyPackageInfoMock = {
+ policy_templates: [
+ {
+ deployment_modes: {
+ default: { enabled: false },
+ agentless: { enabled: true },
+ },
+ },
+ ],
+ } as PackageInfo;
+
+ const { result } = renderHook(() =>
+ useSetupTechnology({
+ setNewAgentPolicy,
+ newAgentPolicy: newAgentPolicyMock,
+ updateAgentPolicies: updateAgentPoliciesMock,
+ setSelectedPolicyTab: setSelectedPolicyTabMock,
+ packageInfo: agentlessOnlyPackageInfoMock,
+ packagePolicy: packagePolicyMock,
+ })
+ );
+
+ expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENTLESS);
+ });
+
it('should fetch agentless policy if agentless feature is enabled and isServerless is true', async () => {
const { waitForNextUpdate } = renderHook(() =>
useSetupTechnology({
@@ -336,8 +404,12 @@ describe('useSetupTechnology', () => {
})
);
+ await rerender();
+
expect(generateNewAgentPolicyWithDefaults).toHaveBeenCalled();
+ expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED);
+
act(() => {
result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS);
});
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts
index 2a88fecc6b145..465a7241b3ad3 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { useCallback, useEffect, useRef, useState } from 'react';
+import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useConfig } from '../../../../../hooks';
import { ExperimentalFeaturesService } from '../../../../../services';
@@ -28,6 +28,7 @@ import {
import {
isAgentlessIntegration as isAgentlessIntegrationFn,
getAgentlessAgentPolicyNameFromPackagePolicyName,
+ isOnlyAgentlessIntegration,
} from '../../../../../../../../common/services/agentless_policy_helper';
export const useAgentless = () => {
@@ -97,9 +98,13 @@ export function useSetupTechnology({
// this is a placeholder for the new agent-BASED policy that will be used when the user switches from agentless to agent-based and back
const newAgentBasedPolicy = useRef(newAgentPolicy);
- const [selectedSetupTechnology, setSelectedSetupTechnology] = useState(
- SetupTechnology.AGENT_BASED
- );
+ const defaultSetupTechnology = useMemo(() => {
+ return isOnlyAgentlessIntegration(packageInfo)
+ ? SetupTechnology.AGENTLESS
+ : SetupTechnology.AGENT_BASED;
+ }, [packageInfo]);
+ const [selectedSetupTechnology, setSelectedSetupTechnology] =
+ useState(defaultSetupTechnology);
const [newAgentlessPolicy, setNewAgentlessPolicy] = useState(() => {
const agentless = generateNewAgentPolicyWithDefaults({
inactivity_timeout: 3600,
@@ -154,6 +159,13 @@ export function useSetupTechnology({
}
}, [isDefaultAgentlessPolicyEnabled]);
+ useEffect(() => {
+ if (isEditPage) {
+ return;
+ }
+ setSelectedSetupTechnology(defaultSetupTechnology);
+ }, [packageInfo, defaultSetupTechnology, isEditPage]);
+
const handleSetupTechnologyChange = useCallback(
(setupTechnology: SetupTechnology, policyTemplateName?: string) => {
if (!isAgentlessEnabled || setupTechnology === selectedSetupTechnology) {
diff --git a/x-pack/plugins/lens/public/visualizations/metric/suggestions.test.ts b/x-pack/plugins/lens/public/visualizations/metric/suggestions.test.ts
index 4f1c7b46d06be..c9a97c0d170a0 100644
--- a/x-pack/plugins/lens/public/visualizations/metric/suggestions.test.ts
+++ b/x-pack/plugins/lens/public/visualizations/metric/suggestions.test.ts
@@ -189,7 +189,7 @@ describe('metric suggestions', () => {
breakdownByAccessor: bucketColumn.columnId,
},
title: 'Metric',
- hide: false,
+ hide: true,
previewIcon: IconChartMetric,
score: 0.51,
},
@@ -221,7 +221,7 @@ describe('metric suggestions', () => {
breakdownByAccessor: bucketColumn.columnId,
},
title: 'Metric',
- hide: false,
+ hide: true,
previewIcon: IconChartMetric,
score: 0.51,
},
@@ -294,7 +294,7 @@ describe('metric suggestions', () => {
breakdownByAccessor: bucketColumn.columnId,
},
title: 'Metric',
- hide: false,
+ hide: true,
previewIcon: IconChartMetric,
score: 0.52,
},
@@ -326,7 +326,7 @@ describe('metric suggestions', () => {
breakdownByAccessor: bucketColumn.columnId,
},
title: 'Metric',
- hide: false,
+ hide: true,
previewIcon: IconChartMetric,
score: 0.52,
},
@@ -357,7 +357,7 @@ describe('metric suggestions', () => {
breakdownByAccessor: bucketColumn.columnId,
},
title: 'Metric',
- hide: false,
+ hide: true,
previewIcon: IconChartMetric,
score: 0.52,
},
diff --git a/x-pack/plugins/lens/public/visualizations/metric/suggestions.ts b/x-pack/plugins/lens/public/visualizations/metric/suggestions.ts
index 877d2b45d66af..5d066318d734f 100644
--- a/x-pack/plugins/lens/public/visualizations/metric/suggestions.ts
+++ b/x-pack/plugins/lens/public/visualizations/metric/suggestions.ts
@@ -30,8 +30,6 @@ export const getSuggestions: Visualization['getSuggest
const bucketedColumns = table.columns.filter(({ operation }) => operation.isBucketed);
- const hasInterval = bucketedColumns.some(({ operation }) => operation.scale === 'interval');
-
const unsupportedColumns = table.columns.filter(
({ operation }) => !supportedDataTypes.has(operation.dataType) && !operation.isBucketed
);
@@ -64,7 +62,7 @@ export const getSuggestions: Visualization['getSuggest
title: metricColumns[0]?.operation.label || metricLabel,
previewIcon: IconChartMetric,
score: 0.5,
- hide: hasInterval,
+ hide: !!bucketedColumns.length,
};
const accessorMappings: Pick =
diff --git a/x-pack/plugins/observability_solution/inventory/.storybook/get_mock_inventory_context.tsx b/x-pack/plugins/observability_solution/inventory/.storybook/get_mock_inventory_context.tsx
index 9c2ea13cf753e..d3d28fe040198 100644
--- a/x-pack/plugins/observability_solution/inventory/.storybook/get_mock_inventory_context.tsx
+++ b/x-pack/plugins/observability_solution/inventory/.storybook/get_mock_inventory_context.tsx
@@ -17,7 +17,7 @@ import type { SpacesPluginStart } from '@kbn/spaces-plugin/public';
import type { HttpStart } from '@kbn/core-http-browser';
import { action } from '@storybook/addon-actions';
import type { InventoryKibanaContext } from '../public/hooks/use_kibana';
-import type { ITelemetryClient } from '../public/services/telemetry/types';
+import { ITelemetryClient } from '../public/services/telemetry/types';
export function getMockInventoryContext(): InventoryKibanaContext {
const coreStart = coreMock.createStart();
diff --git a/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/entity_name/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/entity_name/index.tsx
index f3488dfddbc4e..982a616da8fda 100644
--- a/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/entity_name/index.tsx
+++ b/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/entity_name/index.tsx
@@ -25,13 +25,22 @@ interface EntityNameProps {
}
export function EntityName({ entity }: EntityNameProps) {
- const { services } = useKibana();
+ const {
+ services: { telemetry, share },
+ } = useKibana();
const assetDetailsLocator =
- services.share?.url.locators.get(ASSET_DETAILS_LOCATOR_ID);
+ share?.url.locators.get(ASSET_DETAILS_LOCATOR_ID);
const serviceOverviewLocator =
- services.share?.url.locators.get('serviceOverviewLocator');
+ share?.url.locators.get('serviceOverviewLocator');
+
+ const handleLinkClick = useCallback(() => {
+ telemetry.reportEntityViewClicked({
+ view_type: 'detail',
+ entity_type: entity['entity.type'],
+ });
+ }, [entity, telemetry]);
const getEntityRedirectUrl = useCallback(() => {
const type = entity[ENTITY_TYPE];
@@ -58,7 +67,12 @@ export function EntityName({ entity }: EntityNameProps) {
}, [entity, assetDetailsLocator, serviceOverviewLocator]);
return (
-
+ // eslint-disable-next-line @elastic/eui/href-or-on-click
+
diff --git a/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx
index 6d65669c61651..e3c0d24837f91 100644
--- a/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx
+++ b/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx
@@ -84,12 +84,13 @@ export function EntitiesGrid({
}
const columnEntityTableId = columnId as EntityColumnIds;
+ const entityType = entity[ENTITY_TYPE];
+
switch (columnEntityTableId) {
case 'alertsCount':
return entity?.alertsCount ? : null;
case ENTITY_TYPE:
- const entityType = entity[columnEntityTableId];
return (
@@ -36,7 +37,7 @@ const INVENTORY_FEEDBACK_LINK = 'https://ela.st/feedback-new-inventory';
export function InventoryPageTemplate({ children }: { children: React.ReactNode }) {
const {
- services: { observabilityShared, inventoryAPIClient, kibanaEnvironment },
+ services: { observabilityShared, inventoryAPIClient, kibanaEnvironment, telemetry },
} = useKibana();
const { PageTemplate: ObservabilityPageTemplate } = observabilityShared.navigation;
@@ -62,6 +63,23 @@ export function InventoryPageTemplate({ children }: { children: React.ReactNode
[inventoryAPIClient]
);
+ const isLoadingComplete = useIsLoadingComplete({
+ loadingStates: [isEnablementLoading, hasDataLoading],
+ });
+
+ useEffect(() => {
+ if (isLoadingComplete) {
+ const viewState = isEntityManagerEnabled
+ ? value.hasData
+ ? 'populated'
+ : 'empty'
+ : 'eem_disabled';
+ telemetry.reportEntityInventoryViewed({
+ view_state: viewState,
+ });
+ }
+ }, [isEntityManagerEnabled, value.hasData, telemetry, isLoadingComplete]);
+
if (isEnablementLoading || hasDataLoading) {
return (
{
+ telemetry.reportEntityInventorySearchQuerySubmitted({
+ kuery_fields: getKqlFieldsWithFallback(searchQuery?.query as string),
+ entity_types: searchEntityTypes || [],
+ action: searchIsUpdate ? 'submit' : 'refresh',
+ });
+ },
+ [telemetry]
+ );
+
+ const registerEntityTypeFilteredEvent = useCallback(
+ ({ filterEntityTypes, filterKuery }: { filterEntityTypes: string[]; filterKuery?: string }) => {
+ telemetry.reportEntityInventoryEntityTypeFiltered({
+ entity_types: filterEntityTypes,
+ kuery_fields: filterKuery ? getKqlFieldsWithFallback(filterKuery) : [],
+ });
+ },
+ [telemetry]
+ );
+
const handleEntityTypesChange = useCallback(
(nextEntityTypes: string[]) => {
searchBarContentSubject$.next({ kuery, entityTypes: nextEntityTypes, refresh: false });
+ registerEntityTypeFilteredEvent({ filterEntityTypes: nextEntityTypes, filterKuery: kuery });
},
- [kuery, searchBarContentSubject$]
+ [kuery, registerEntityTypeFilteredEvent, searchBarContentSubject$]
);
const handleQuerySubmit = useCallback>(
@@ -64,8 +97,14 @@ export function SearchBar() {
entityTypes,
refresh: !isUpdate,
});
+
+ registerSearchSubmittedEvent({
+ searchQuery: query,
+ searchEntityTypes: entityTypes,
+ searchIsUpdate: isUpdate,
+ });
},
- [entityTypes, searchBarContentSubject$]
+ [entityTypes, registerSearchSubmittedEvent, searchBarContentSubject$]
);
return (
diff --git a/x-pack/plugins/observability_solution/inventory/public/hooks/use_is_loading_complete.test.ts b/x-pack/plugins/observability_solution/inventory/public/hooks/use_is_loading_complete.test.ts
new file mode 100644
index 0000000000000..61306a0b66a3b
--- /dev/null
+++ b/x-pack/plugins/observability_solution/inventory/public/hooks/use_is_loading_complete.test.ts
@@ -0,0 +1,109 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { renderHook } from '@testing-library/react-hooks';
+import { useIsLoadingComplete } from './use_is_loading_complete';
+
+describe('useIsLoadingComplete', () => {
+ describe('initialization', () => {
+ it('should initialize with undefined', () => {
+ const { result } = renderHook(() => useIsLoadingComplete({ loadingStates: [false, false] }));
+ expect(result.current).toBeUndefined();
+ });
+
+ it('should handle an empty array of loadingStates', () => {
+ const { result } = renderHook(() => useIsLoadingComplete({ loadingStates: [] }));
+ expect(result.current).toBeUndefined();
+ });
+
+ it('should handle a single loading state that is false', () => {
+ const { result } = renderHook(() => useIsLoadingComplete({ loadingStates: [false] }));
+ expect(result.current).toBeUndefined();
+ });
+ });
+
+ describe('loading states', () => {
+ it('should set isLoadingComplete to false when some loadingStates are true', () => {
+ const { result } = renderHook(() => useIsLoadingComplete({ loadingStates: [true, false] }));
+ expect(result.current).toBe(false);
+ });
+
+ it('should set isLoadingComplete to false when all loadingStates are true', () => {
+ const { result } = renderHook(() => useIsLoadingComplete({ loadingStates: [true, true] }));
+ expect(result.current).toBe(false);
+ });
+
+ it('should handle a single loading state that is true', () => {
+ const { result } = renderHook(() => useIsLoadingComplete({ loadingStates: [true] }));
+ expect(result.current).toBe(false);
+ });
+ });
+
+ describe('loading completion', () => {
+ it('should set isLoadingComplete to true when all loadingStates are false after being true', () => {
+ const { result, rerender } = renderHook(
+ ({ loadingStates }) => useIsLoadingComplete({ loadingStates }),
+ {
+ initialProps: { loadingStates: [true, false] },
+ }
+ );
+
+ expect(result.current).toBe(false);
+
+ rerender({ loadingStates: [false, false] });
+
+ expect(result.current).toBe(true);
+ });
+
+ it('should set isLoadingComplete to true when all loadingStates are false after being mixed', () => {
+ const { result, rerender } = renderHook(
+ ({ loadingStates }) => useIsLoadingComplete({ loadingStates }),
+ {
+ initialProps: { loadingStates: [true, false] },
+ }
+ );
+
+ expect(result.current).toBe(false);
+
+ rerender({ loadingStates: [false, false] });
+
+ expect(result.current).toBe(true);
+ });
+ });
+
+ describe('mixed states', () => {
+ it('should not change isLoadingComplete if loadingStates are mixed', () => {
+ const { result, rerender } = renderHook(
+ ({ loadingStates }) => useIsLoadingComplete({ loadingStates }),
+ {
+ initialProps: { loadingStates: [true, true] },
+ }
+ );
+
+ expect(result.current).toBe(false);
+
+ rerender({ loadingStates: [true, false] });
+
+ expect(result.current).toBe(false);
+ });
+
+ it('should not change isLoadingComplete if loadingStates change from all true to mixed', () => {
+ const { result, rerender } = renderHook(
+ ({ loadingStates }) => useIsLoadingComplete({ loadingStates }),
+ {
+ initialProps: { loadingStates: [true, true] },
+ }
+ );
+
+ expect(result.current).toBe(false);
+
+ rerender({ loadingStates: [true, false] });
+
+ expect(result.current).toBe(false);
+ });
+ });
+});
diff --git a/x-pack/plugins/observability_solution/inventory/public/hooks/use_is_loading_complete.ts b/x-pack/plugins/observability_solution/inventory/public/hooks/use_is_loading_complete.ts
new file mode 100644
index 0000000000000..76b863efaeceb
--- /dev/null
+++ b/x-pack/plugins/observability_solution/inventory/public/hooks/use_is_loading_complete.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 { useState, useEffect } from 'react';
+
+interface UseIsLoadingCompleteProps {
+ loadingStates: boolean[];
+}
+
+export const useIsLoadingComplete = ({ loadingStates }: UseIsLoadingCompleteProps) => {
+ const [isLoadingComplete, setIsLoadingComplete] = useState(undefined);
+
+ useEffect(() => {
+ const someLoading = loadingStates.some((loading) => loading);
+ const allLoaded = loadingStates.every((loading) => !loading);
+
+ if (isLoadingComplete === undefined && someLoading) {
+ setIsLoadingComplete(false);
+ } else if (isLoadingComplete === false && allLoaded) {
+ setIsLoadingComplete(true);
+ }
+ }, [isLoadingComplete, loadingStates]);
+
+ return isLoadingComplete;
+};
diff --git a/x-pack/plugins/observability_solution/inventory/public/plugin.ts b/x-pack/plugins/observability_solution/inventory/public/plugin.ts
index b6771d2f95550..109123859d4ca 100644
--- a/x-pack/plugins/observability_solution/inventory/public/plugin.ts
+++ b/x-pack/plugins/observability_solution/inventory/public/plugin.ts
@@ -49,6 +49,7 @@ export class InventoryPlugin
this.kibanaVersion = context.env.packageInfo.version;
this.isServerlessEnv = context.env.packageInfo.buildFlavor === 'serverless';
}
+
setup(
coreSetup: CoreSetup,
pluginsSetup: InventorySetupDependencies
@@ -58,6 +59,13 @@ export class InventoryPlugin
'observability:entityCentricExperience',
true
);
+
+ this.telemetry.setup({
+ analytics: coreSetup.analytics,
+ });
+
+ const telemetry = this.telemetry.start();
+
const getStartServices = coreSetup.getStartServices();
const hideInventory$ = from(getStartServices).pipe(
@@ -105,9 +113,6 @@ export class InventoryPlugin
pluginsSetup.observabilityShared.navigation.registerSections(sections$);
- this.telemetry.setup({ analytics: coreSetup.analytics });
- const telemetry = this.telemetry.start();
-
const isCloudEnv = !!pluginsSetup.cloud?.isCloudEnabled;
const isServerlessEnv = pluginsSetup.cloud?.isServerlessEnabled || this.isServerlessEnv;
diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts
index 1e36e8d6649ae..54d20ea324b11 100644
--- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts
+++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts
@@ -6,7 +6,16 @@
*/
import { AnalyticsServiceSetup } from '@kbn/core-analytics-browser';
-import { type ITelemetryClient, TelemetryEventTypes, type InventoryAddDataParams } from './types';
+
+import {
+ type ITelemetryClient,
+ TelemetryEventTypes,
+ type InventoryAddDataParams,
+ type EntityInventoryViewedParams,
+ type EntityInventorySearchQuerySubmittedParams,
+ type EntityViewClickedParams,
+ type EntityInventoryEntityTypeFilteredParams,
+} from './types';
export class TelemetryClient implements ITelemetryClient {
constructor(private analytics: AnalyticsServiceSetup) {}
@@ -14,4 +23,24 @@ export class TelemetryClient implements ITelemetryClient {
public reportInventoryAddData = (params: InventoryAddDataParams) => {
this.analytics.reportEvent(TelemetryEventTypes.INVENTORY_ADD_DATA_CLICKED, params);
};
+
+ public reportEntityInventoryViewed = (params: EntityInventoryViewedParams) => {
+ this.analytics.reportEvent(TelemetryEventTypes.ENTITY_INVENTORY_VIEWED, params);
+ };
+
+ public reportEntityInventorySearchQuerySubmitted = (
+ params: EntityInventorySearchQuerySubmittedParams
+ ) => {
+ this.analytics.reportEvent(TelemetryEventTypes.ENTITY_INVENTORY_SEARCH_QUERY_SUBMITTED, params);
+ };
+
+ public reportEntityInventoryEntityTypeFiltered = (
+ params: EntityInventoryEntityTypeFilteredParams
+ ) => {
+ this.analytics.reportEvent(TelemetryEventTypes.ENTITY_INVENTORY_ENTITY_TYPE_FILTERED, params);
+ };
+
+ public reportEntityViewClicked = (params: EntityViewClickedParams) => {
+ this.analytics.reportEvent(TelemetryEventTypes.ENTITY_VIEW_CLICKED, params);
+ };
}
diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts
index c1509499e694b..d61a90f7d30ab 100644
--- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts
+++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts
@@ -25,4 +25,94 @@ const inventoryAddDataEventType: TelemetryEvent = {
},
};
-export const inventoryTelemetryEventBasedTypes = [inventoryAddDataEventType];
+const entityInventoryViewedEventType: TelemetryEvent = {
+ eventType: TelemetryEventTypes.ENTITY_INVENTORY_VIEWED,
+ schema: {
+ view_state: {
+ type: 'keyword',
+ _meta: {
+ description: 'State of the view: empty, populated or eem_disabled.',
+ },
+ },
+ },
+};
+
+const searchQuerySubmittedEventType: TelemetryEvent = {
+ eventType: TelemetryEventTypes.ENTITY_INVENTORY_SEARCH_QUERY_SUBMITTED,
+ schema: {
+ kuery_fields: {
+ type: 'array',
+ items: {
+ type: 'text',
+ _meta: {
+ description: 'Kuery fields used in the search.',
+ },
+ },
+ },
+ entity_types: {
+ type: 'array',
+ items: {
+ type: 'keyword',
+ _meta: {
+ description: 'Entity types used in the search.',
+ },
+ },
+ },
+ action: {
+ type: 'keyword',
+ _meta: {
+ description: 'Action performed: submit or refresh.',
+ },
+ },
+ },
+};
+
+const entityInventoryEntityTypeFilteredEventType: TelemetryEvent = {
+ eventType: TelemetryEventTypes.ENTITY_INVENTORY_ENTITY_TYPE_FILTERED,
+ schema: {
+ entity_types: {
+ type: 'array',
+ items: {
+ type: 'keyword',
+ _meta: {
+ description: 'Entity types used in the filter.',
+ },
+ },
+ },
+ kuery_fields: {
+ type: 'array',
+ items: {
+ type: 'text',
+ _meta: {
+ description: 'Kuery fields used in the filter.',
+ },
+ },
+ },
+ },
+};
+
+const entityViewClickedEventType: TelemetryEvent = {
+ eventType: TelemetryEventTypes.ENTITY_VIEW_CLICKED,
+ schema: {
+ entity_type: {
+ type: 'keyword',
+ _meta: {
+ description: 'Type of the entity: container, host or service.',
+ },
+ },
+ view_type: {
+ type: 'keyword',
+ _meta: {
+ description: 'Type of the view: detail or flyout.',
+ },
+ },
+ },
+};
+
+export const inventoryTelemetryEventBasedTypes = [
+ inventoryAddDataEventType,
+ entityInventoryViewedEventType,
+ searchQuerySubmittedEventType,
+ entityInventoryEntityTypeFilteredEventType,
+ entityViewClickedEventType,
+];
diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts
index ffa05ffbff9a2..415cf0e7d4406 100644
--- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts
+++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts
@@ -8,7 +8,13 @@ import { coreMock } from '@kbn/core/server/mocks';
import { inventoryTelemetryEventBasedTypes } from './telemetry_events';
import { TelemetryService } from './telemetry_service';
-import { TelemetryEventTypes } from './types';
+import {
+ type EntityInventoryViewedParams,
+ type EntityViewClickedParams,
+ type EntityInventorySearchQuerySubmittedParams,
+ TelemetryEventTypes,
+ type EntityInventoryEntityTypeFilteredParams,
+} from './types';
describe('TelemetryService', () => {
let service: TelemetryService;
@@ -48,7 +54,15 @@ describe('TelemetryService', () => {
service.setup(setupParams);
const telemetry = service.start();
- expect(telemetry).toHaveProperty('reportInventoryAddData');
+ const expectedProperties = [
+ 'reportInventoryAddData',
+ 'reportEntityInventoryViewed',
+ 'reportEntityInventorySearchQuerySubmitted',
+ 'reportEntityViewClicked',
+ ];
+ expectedProperties.forEach((property) => {
+ expect(telemetry).toHaveProperty(property);
+ });
});
});
@@ -73,4 +87,84 @@ describe('TelemetryService', () => {
);
});
});
+
+ describe('#reportEntityInventoryViewed', () => {
+ it('should report entity inventory viewed with properties', async () => {
+ const setupParams = getSetupParams();
+ service.setup(setupParams);
+ const telemetry = service.start();
+ const params: EntityInventoryViewedParams = {
+ view_state: 'empty',
+ };
+
+ telemetry.reportEntityInventoryViewed(params);
+
+ expect(setupParams.analytics.reportEvent).toHaveBeenCalledTimes(1);
+ expect(setupParams.analytics.reportEvent).toHaveBeenCalledWith(
+ TelemetryEventTypes.ENTITY_INVENTORY_VIEWED,
+ params
+ );
+ });
+ });
+
+ describe('#reportEntityInventorySearchQuerySubmitted', () => {
+ it('should report search query submitted with properties', async () => {
+ const setupParams = getSetupParams();
+ service.setup(setupParams);
+ const telemetry = service.start();
+ const params: EntityInventorySearchQuerySubmittedParams = {
+ kuery_fields: ['_index'],
+ action: 'submit',
+ entity_types: ['container'],
+ };
+
+ telemetry.reportEntityInventorySearchQuerySubmitted(params);
+
+ expect(setupParams.analytics.reportEvent).toHaveBeenCalledTimes(1);
+ expect(setupParams.analytics.reportEvent).toHaveBeenCalledWith(
+ TelemetryEventTypes.ENTITY_INVENTORY_SEARCH_QUERY_SUBMITTED,
+ params
+ );
+ });
+ });
+
+ describe('#reportEntityInventoryEntityTypeFiltered', () => {
+ it('should report entity type filtered with properties', async () => {
+ const setupParams = getSetupParams();
+ service.setup(setupParams);
+ const telemetry = service.start();
+ const params: EntityInventoryEntityTypeFilteredParams = {
+ kuery_fields: ['_index'],
+ entity_types: ['container'],
+ };
+
+ telemetry.reportEntityInventoryEntityTypeFiltered(params);
+
+ expect(setupParams.analytics.reportEvent).toHaveBeenCalledTimes(1);
+ expect(setupParams.analytics.reportEvent).toHaveBeenCalledWith(
+ TelemetryEventTypes.ENTITY_INVENTORY_ENTITY_TYPE_FILTERED,
+ params
+ );
+ });
+ });
+
+ describe('#reportEntityViewClicked', () => {
+ it('should report entity view clicked with properties', async () => {
+ const setupParams = getSetupParams();
+ service.setup(setupParams);
+ const telemetry = service.start();
+ const params: EntityViewClickedParams = {
+ entity_type: 'container',
+ view_type: 'detail',
+ };
+
+ telemetry.reportEntityViewClicked(params);
+
+ expect(setupParams.analytics.reportEvent).toHaveBeenCalledTimes(1);
+ expect(setupParams.analytics.reportEvent).toHaveBeenCalledWith(
+ TelemetryEventTypes.ENTITY_VIEW_CLICKED,
+ params
+ );
+ });
+ });
});
diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.ts
index fa416f76b3c16..b81aff39672bb 100644
--- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.ts
+++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
import type { AnalyticsServiceSetup } from '@kbn/core-analytics-browser';
-import type { TelemetryServiceSetupParams, ITelemetryClient, TelemetryEventParams } from './types';
+import type { TelemetryServiceSetupParams, TelemetryEventParams } from './types';
import { inventoryTelemetryEventBasedTypes } from './telemetry_events';
import { TelemetryClient } from './telemetry_client';
@@ -23,7 +23,7 @@ export class TelemetryService {
);
}
- public start(): ITelemetryClient {
+ public start(): TelemetryClient {
if (!this.analytics) {
throw new Error(
'The TelemetryService.setup() method has not been invoked, be sure to call it during the plugin setup.'
diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts
index e5fdf162b750c..0e52d115d4597 100644
--- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts
+++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts
@@ -6,24 +6,64 @@
*/
import type { AnalyticsServiceSetup, RootSchema } from '@kbn/core/public';
+import { EntityManagerPublicPluginSetup } from '@kbn/entityManager-plugin/public';
export interface TelemetryServiceSetupParams {
analytics: AnalyticsServiceSetup;
}
+export interface TelemetryServiceStartParams {
+ entityManager: EntityManagerPublicPluginSetup;
+}
+
export interface InventoryAddDataParams {
view: 'add_data_button' | 'empty_state';
journey?: 'add_data' | 'associate_existing_service_logs';
}
-export type TelemetryEventParams = InventoryAddDataParams;
+export interface EntityInventoryViewedParams {
+ view_state: 'empty' | 'populated' | 'eem_disabled';
+}
+
+export interface EntityInventorySearchQuerySubmittedParams {
+ kuery_fields: string[];
+ entity_types: string[];
+ action: 'submit' | 'refresh';
+}
+
+export interface EntityInventoryEntityTypeFilteredParams {
+ kuery_fields: string[];
+ entity_types: string[];
+}
+
+export interface EntityViewClickedParams {
+ entity_type: string;
+ view_type: 'detail' | 'flyout';
+}
+
+export type TelemetryEventParams =
+ | InventoryAddDataParams
+ | EntityInventoryViewedParams
+ | EntityInventorySearchQuerySubmittedParams
+ | EntityInventoryEntityTypeFilteredParams
+ | EntityViewClickedParams;
export interface ITelemetryClient {
reportInventoryAddData(params: InventoryAddDataParams): void;
+ reportEntityInventoryViewed(params: EntityInventoryViewedParams): void;
+ reportEntityInventorySearchQuerySubmitted(
+ params: EntityInventorySearchQuerySubmittedParams
+ ): void;
+ reportEntityInventoryEntityTypeFiltered(params: EntityInventoryEntityTypeFilteredParams): void;
+ reportEntityViewClicked(params: EntityViewClickedParams): void;
}
export enum TelemetryEventTypes {
INVENTORY_ADD_DATA_CLICKED = 'inventory_add_data_clicked',
+ ENTITY_INVENTORY_VIEWED = 'Entity Inventory Viewed',
+ ENTITY_INVENTORY_SEARCH_QUERY_SUBMITTED = 'Entity Inventory Search Query Submitted',
+ ENTITY_INVENTORY_ENTITY_TYPE_FILTERED = 'Entity Inventory Entity Type Filtered',
+ ENTITY_VIEW_CLICKED = 'Entity View Clicked',
}
export interface TelemetryEvent {
diff --git a/x-pack/plugins/observability_solution/inventory/public/services/types.ts b/x-pack/plugins/observability_solution/inventory/public/services/types.ts
index d0cc176e7b53f..b498a1fd49079 100644
--- a/x-pack/plugins/observability_solution/inventory/public/services/types.ts
+++ b/x-pack/plugins/observability_solution/inventory/public/services/types.ts
@@ -6,7 +6,7 @@
*/
import type { InventoryAPIClient } from '../api';
-import type { ITelemetryClient } from './telemetry/types';
+import { ITelemetryClient } from './telemetry/types';
export interface InventoryServices {
inventoryAPIClient: InventoryAPIClient;
diff --git a/x-pack/plugins/observability_solution/inventory/public/utils/get_kql_field_names_with_fallback.test.ts b/x-pack/plugins/observability_solution/inventory/public/utils/get_kql_field_names_with_fallback.test.ts
new file mode 100644
index 0000000000000..89305e2bb08c9
--- /dev/null
+++ b/x-pack/plugins/observability_solution/inventory/public/utils/get_kql_field_names_with_fallback.test.ts
@@ -0,0 +1,44 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { getKqlFieldsWithFallback } from './get_kql_field_names_with_fallback';
+import { getKqlFieldNamesFromExpression } from '@kbn/es-query';
+
+jest.mock('@kbn/es-query', () => ({
+ getKqlFieldNamesFromExpression: jest.fn(),
+}));
+
+describe('getKqlFieldsWithFallback', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('should return field names when getKqlFieldNamesFromExpression succeeds', () => {
+ const mockFieldNames = ['field1', 'field2'];
+ (getKqlFieldNamesFromExpression as jest.Mock).mockReturnValue(mockFieldNames);
+ const expectedArg = 'testKuery';
+
+ const result = getKqlFieldsWithFallback(expectedArg);
+ expect(result).toEqual(mockFieldNames);
+ expect(getKqlFieldNamesFromExpression).toHaveBeenCalledWith(expectedArg);
+ });
+
+ it('should return an empty array when getKqlFieldNamesFromExpression throws an error', () => {
+ (getKqlFieldNamesFromExpression as jest.Mock).mockImplementation(() => {
+ throw new Error('Test error');
+ });
+ const expectedArg = 'testKuery';
+
+ const result = getKqlFieldsWithFallback(expectedArg);
+ expect(result).toEqual([]);
+ expect(getKqlFieldNamesFromExpression).toHaveBeenCalledWith(expectedArg);
+ });
+});
diff --git a/x-pack/plugins/observability_solution/inventory/public/utils/get_kql_field_names_with_fallback.ts b/x-pack/plugins/observability_solution/inventory/public/utils/get_kql_field_names_with_fallback.ts
new file mode 100644
index 0000000000000..029405b5fc235
--- /dev/null
+++ b/x-pack/plugins/observability_solution/inventory/public/utils/get_kql_field_names_with_fallback.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 { getKqlFieldNamesFromExpression } from '@kbn/es-query';
+
+export function getKqlFieldsWithFallback(kuery: string): string[] {
+ try {
+ return getKqlFieldNamesFromExpression(kuery);
+ } catch (e) {
+ return [];
+ }
+}
diff --git a/x-pack/plugins/observability_solution/observability/public/navigation_tree.ts b/x-pack/plugins/observability_solution/observability/public/navigation_tree.ts
index a36c85dbf937a..07bb33ebb5a98 100644
--- a/x-pack/plugins/observability_solution/observability/public/navigation_tree.ts
+++ b/x-pack/plugins/observability_solution/observability/public/navigation_tree.ts
@@ -325,6 +325,15 @@ export function createNavTree(pluginsStart: ObservabilityPublicPluginsStart) {
}
),
},
+ {
+ link: 'ml:esqlDataVisualizer',
+ title: i18n.translate(
+ 'xpack.observability.obltNav.ml.data_visualizer.esql_data_visualizer',
+ {
+ defaultMessage: 'ES|QL data visualizer',
+ }
+ ),
+ },
{
link: 'ml:dataDrift',
title: i18n.translate(
diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/global_parameters.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/global_parameters.journey.ts
index 831f8d107f36a..b328b273836a7 100644
--- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/global_parameters.journey.ts
+++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/global_parameters.journey.ts
@@ -76,8 +76,8 @@ journey(`GlobalParameters`, async ({ page, params }) => {
await page.click('text=Delete ParameterEdit Parameter >> :nth-match(button, 2)');
await page.click('[aria-label="Key"]');
await page.fill('[aria-label="Key"]', 'username2');
- await page.click('[aria-label="Value"]');
- await page.fill('[aria-label="Value"]', 'elastic2');
+ await page.click('[aria-label="New value"]');
+ await page.fill('[aria-label="New value"]', 'elastic2');
await page.click('.euiComboBox__inputWrap');
await page.fill('[aria-label="Tags"]', 'staging');
await page.press('[aria-label="Tags"]', 'Enter');
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/components/optional_text.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/components/optional_text.tsx
new file mode 100644
index 0000000000000..a764cf3b27cdc
--- /dev/null
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/components/optional_text.tsx
@@ -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 { EuiText } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import React from 'react';
+
+export function OptionalText() {
+ return (
+
+ {i18n.translate('xpack.synthetics.sloEdit.optionalLabel', {
+ defaultMessage: 'Optional',
+ })}
+
+ );
+}
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/global_params/add_param_flyout.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/global_params/add_param_flyout.tsx
index 3fd17335d2ea5..70c2eb77526af 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/global_params/add_param_flyout.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/global_params/add_param_flyout.tsx
@@ -22,6 +22,7 @@ import { FormProvider } from 'react-hook-form';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import { i18n } from '@kbn/i18n';
import { useDispatch, useSelector } from 'react-redux';
+import { isEmpty } from 'lodash';
import { NoPermissionsTooltip } from '../../common/components/permissions';
import {
addNewGlobalParamAction,
@@ -80,18 +81,29 @@ export const AddParamFlyout = ({
const onSubmit = (formData: SyntheticsParams) => {
const { namespaces, ...paramRequest } = formData;
const shareAcrossSpaces = namespaces?.includes(ALL_SPACES_ID);
+ const newParamData = {
+ ...paramRequest,
+ };
+
+ if (isEditingItem && id) {
+ // omit value if it's empty
+ if (isEmpty(newParamData.value)) {
+ // @ts-ignore this is a valid check
+ delete newParamData.value;
+ }
+ }
if (isEditingItem && id) {
dispatch(
editGlobalParamAction.get({
id,
- paramRequest: { ...paramRequest, share_across_spaces: shareAcrossSpaces },
+ paramRequest,
})
);
} else {
dispatch(
addNewGlobalParamAction.get({
- ...paramRequest,
+ ...newParamData,
share_across_spaces: shareAcrossSpaces,
})
);
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/global_params/add_param_form.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/global_params/add_param_form.tsx
index 1b219a0f6fec4..d472ec62237e9 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/global_params/add_param_form.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/global_params/add_param_form.tsx
@@ -6,16 +6,11 @@
*/
import React from 'react';
import { ALL_SPACES_ID } from '@kbn/security-plugin/public';
-import {
- EuiCheckbox,
- EuiComboBox,
- EuiFieldText,
- EuiForm,
- EuiFormRow,
- EuiTextArea,
-} from '@elastic/eui';
+import { EuiCheckbox, EuiComboBox, EuiFieldText, EuiForm, EuiFormRow } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { Controller, useFormContext, useFormState } from 'react-hook-form';
+import { OptionalText } from '../components/optional_text';
+import { ParamValueField } from './param_value_field';
import { SyntheticsParams } from '../../../../../../common/runtime_types';
import { ListParamItem } from './params_list';
@@ -61,25 +56,8 @@ export const AddParamForm = ({
})}
/>
-
-
-
-
+
+ }>
-
+ }>
{
+ const { register } = useFormContext();
+ const { errors } = useFormState();
+
+ if (isEditingItem) {
+ return (
+ <>
+ }
+ >
+
+
+
+
+ >
+ );
+ }
+
+ return (
+
+
+
+ );
+};
+
+export const NEW_VALUE_LABEL = i18n.translate(
+ 'xpack.synthetics.monitorManagement.paramForm.newValue',
+ {
+ defaultMessage: 'New value',
+ }
+);
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/global_params/api.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/global_params/api.ts
index ce7f9bd81ea3d..33eb4622bf6c5 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/global_params/api.ts
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/global_params/api.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import { isEmpty } from 'lodash';
import { INITIAL_REST_VERSION, SYNTHETICS_API_URLS } from '../../../../../common/constants';
import {
DeleteParamsResponse,
@@ -35,16 +36,22 @@ export const editGlobalParam = async ({
id,
}: {
id: string;
- paramRequest: SyntheticsParamRequest;
-}): Promise =>
- apiService.put(
+ paramRequest: Partial;
+}): Promise => {
+ const data = paramRequest;
+ if (isEmpty(paramRequest.value)) {
+ // omit empty value
+ delete data.value;
+ }
+ return await apiService.put(
SYNTHETICS_API_URLS.PARAMS + `/${id}`,
- paramRequest,
+ data,
SyntheticsParamsCodec,
{
version: INITIAL_REST_VERSION,
}
);
+};
export const deleteGlobalParams = async (ids: string[]): Promise =>
apiService.delete(
diff --git a/x-pack/plugins/observability_solution/synthetics/server/routes/common.ts b/x-pack/plugins/observability_solution/synthetics/server/routes/common.ts
index 0bdc7989b8a8a..2a906f3cf6a4d 100644
--- a/x-pack/plugins/observability_solution/synthetics/server/routes/common.ts
+++ b/x-pack/plugins/observability_solution/synthetics/server/routes/common.ts
@@ -9,6 +9,7 @@ import { schema, TypeOf } from '@kbn/config-schema';
import { SavedObjectsFindResponse } from '@kbn/core/server';
import { isEmpty } from 'lodash';
import { escapeQuotes } from '@kbn/es-query';
+import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
import { RouteContext } from './types';
import { MonitorSortFieldSchema } from '../../common/runtime_types/monitor_management/sort_field';
import { getAllLocations } from '../synthetics_service/get_all_locations';
@@ -269,3 +270,26 @@ function parseMappingKey(key: string | undefined) {
return key;
}
}
+
+export const validateRouteSpaceName = async (routeContext: RouteContext) => {
+ const { spaceId, server, request, response } = routeContext;
+ if (spaceId === DEFAULT_SPACE_ID) {
+ // default space is always valid
+ return { spaceId: DEFAULT_SPACE_ID };
+ }
+
+ try {
+ await server.spaces?.spacesService.getActiveSpace(request);
+ } catch (error) {
+ if (error.output?.statusCode === 404) {
+ return {
+ spaceId,
+ invalidResponse: response.notFound({
+ body: { message: `Kibana space '${spaceId}' does not exist` },
+ }),
+ };
+ }
+ }
+
+ return { invalidResponse: undefined };
+};
diff --git a/x-pack/plugins/observability_solution/synthetics/server/routes/settings/params/add_param.ts b/x-pack/plugins/observability_solution/synthetics/server/routes/settings/params/add_param.ts
index a51079f366eff..7d0cac7d7e57c 100644
--- a/x-pack/plugins/observability_solution/synthetics/server/routes/settings/params/add_param.ts
+++ b/x-pack/plugins/observability_solution/synthetics/server/routes/settings/params/add_param.ts
@@ -19,8 +19,12 @@ import { syntheticsParamType } from '../../../../common/types/saved_objects';
import { SYNTHETICS_API_URLS } from '../../../../common/constants';
const ParamsObjectSchema = schema.object({
- key: schema.string(),
- value: schema.string(),
+ key: schema.string({
+ minLength: 1,
+ }),
+ value: schema.string({
+ minLength: 1,
+ }),
description: schema.maybe(schema.string()),
tags: schema.maybe(schema.arrayOf(schema.string())),
share_across_spaces: schema.maybe(schema.boolean()),
diff --git a/x-pack/plugins/observability_solution/synthetics/server/routes/settings/params/edit_param.ts b/x-pack/plugins/observability_solution/synthetics/server/routes/settings/params/edit_param.ts
index 3555963b76bf1..eb9f41696da97 100644
--- a/x-pack/plugins/observability_solution/synthetics/server/routes/settings/params/edit_param.ts
+++ b/x-pack/plugins/observability_solution/synthetics/server/routes/settings/params/edit_param.ts
@@ -6,8 +6,9 @@
*/
import { schema, TypeOf } from '@kbn/config-schema';
-import { SavedObject } from '@kbn/core/server';
-import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
+import { SavedObject, SavedObjectsErrorHelpers } from '@kbn/core/server';
+import { isEmpty } from 'lodash';
+import { validateRouteSpaceName } from '../../common';
import { SyntheticsRestApiRouteFactory } from '../../types';
import { SyntheticsParamRequest, SyntheticsParams } from '../../../../common/runtime_types';
import { syntheticsParamType } from '../../../../common/types/saved_objects';
@@ -20,7 +21,7 @@ const RequestParamsSchema = schema.object({
type RequestParams = TypeOf;
export const editSyntheticsParamsRoute: SyntheticsRestApiRouteFactory<
- SyntheticsParams,
+ SyntheticsParams | undefined,
RequestParams
> = () => ({
method: 'PUT',
@@ -30,46 +31,63 @@ export const editSyntheticsParamsRoute: SyntheticsRestApiRouteFactory<
request: {
params: RequestParamsSchema,
body: schema.object({
- key: schema.string(),
- value: schema.string(),
+ key: schema.maybe(
+ schema.string({
+ minLength: 1,
+ })
+ ),
+ value: schema.maybe(
+ schema.string({
+ minLength: 1,
+ })
+ ),
description: schema.maybe(schema.string()),
tags: schema.maybe(schema.arrayOf(schema.string())),
- share_across_spaces: schema.maybe(schema.boolean()),
}),
},
},
- handler: async ({ savedObjectsClient, request, server, response }) => {
+ handler: async (routeContext) => {
+ const { savedObjectsClient, request, response, spaceId, server } = routeContext;
+ const { invalidResponse } = await validateRouteSpaceName(routeContext);
+ if (invalidResponse) return invalidResponse;
+
+ const { id: paramId } = request.params;
+ const data = request.body as SyntheticsParamRequest;
+ if (isEmpty(data)) {
+ return response.badRequest({ body: { message: 'Request body cannot be empty' } });
+ }
+ const encryptedSavedObjectsClient = server.encryptedSavedObjects.getClient();
+
try {
- const { id: _spaceId } = (await server.spaces?.spacesService.getActiveSpace(request)) ?? {
- id: DEFAULT_SPACE_ID,
+ const existingParam =
+ await encryptedSavedObjectsClient.getDecryptedAsInternalUser(
+ syntheticsParamType,
+ paramId,
+ { namespace: spaceId }
+ );
+
+ const newParam = {
+ ...existingParam.attributes,
+ ...data,
};
- const { id } = request.params;
- const { share_across_spaces: _shareAcrossSpaces, ...data } =
- request.body as SyntheticsParamRequest & {
- id: string;
- };
- const { value } = data;
+ // value from data since we aren't using encrypted client
+ const { value } = existingParam.attributes;
const {
id: responseId,
attributes: { key, tags, description },
namespaces,
- } = (await savedObjectsClient.update(
+ } = (await savedObjectsClient.update(
syntheticsParamType,
- id,
- data
+ paramId,
+ newParam
)) as SavedObject;
return { id: responseId, key, tags, description, namespaces, value };
- } catch (error) {
- if (error.output?.statusCode === 404) {
- const spaceId = server.spaces?.spacesService.getSpaceId(request) ?? DEFAULT_SPACE_ID;
- return response.notFound({
- body: { message: `Kibana space '${spaceId}' does not exist` },
- });
+ } catch (getErr) {
+ if (SavedObjectsErrorHelpers.isNotFoundError(getErr)) {
+ return response.notFound({ body: { message: 'Param not found' } });
}
-
- throw error;
}
},
});
diff --git a/x-pack/plugins/observability_solution/synthetics/server/routes/settings/params/params.ts b/x-pack/plugins/observability_solution/synthetics/server/routes/settings/params/params.ts
index 01f2dd6465dfd..da0a2e250557a 100644
--- a/x-pack/plugins/observability_solution/synthetics/server/routes/settings/params/params.ts
+++ b/x-pack/plugins/observability_solution/synthetics/server/routes/settings/params/params.ts
@@ -7,7 +7,7 @@
import { SavedObject, SavedObjectsFindResult } from '@kbn/core-saved-objects-api-server';
import { schema, TypeOf } from '@kbn/config-schema';
-import { SyntheticsRestApiRouteFactory } from '../../types';
+import { RouteContext, SyntheticsRestApiRouteFactory } from '../../types';
import { syntheticsParamType } from '../../../../common/types/saved_objects';
import { SYNTHETICS_API_URLS } from '../../../../common/constants';
import { SyntheticsParams, SyntheticsParamsReadonly } from '../../../../common/runtime_types';
@@ -30,45 +30,13 @@ export const getSyntheticsParamsRoute: SyntheticsRestApiRouteFactory<
params: RequestParamsSchema,
},
},
- handler: async ({ savedObjectsClient, request, response, server, spaceId }) => {
+ handler: async (routeContext) => {
+ const { savedObjectsClient, request, response, spaceId } = routeContext;
try {
const { id: paramId } = request.params;
- const encryptedSavedObjectsClient = server.encryptedSavedObjects.getClient();
-
- const canSave =
- (
- await server.coreStart?.capabilities.resolveCapabilities(request, {
- capabilityPath: 'uptime.*',
- })
- ).uptime.save ?? false;
-
- if (canSave) {
- if (paramId) {
- const savedObject =
- await encryptedSavedObjectsClient.getDecryptedAsInternalUser(
- syntheticsParamType,
- paramId,
- { namespace: spaceId }
- );
- return toClientResponse(savedObject);
- }
-
- const finder =
- await encryptedSavedObjectsClient.createPointInTimeFinderDecryptedAsInternalUser(
- {
- type: syntheticsParamType,
- perPage: 1000,
- namespaces: [spaceId],
- }
- );
-
- const hits: Array> = [];
- for await (const result of finder.find()) {
- hits.push(...result.saved_objects);
- }
-
- return hits.map((savedObject) => toClientResponse(savedObject));
+ if (await isAnAdminUser(routeContext)) {
+ return getDecryptedParams(routeContext, paramId);
} else {
if (paramId) {
const savedObject = await savedObjectsClient.get(
@@ -78,11 +46,7 @@ export const getSyntheticsParamsRoute: SyntheticsRestApiRouteFactory<
return toClientResponse(savedObject);
}
- const data = await savedObjectsClient.find({
- type: syntheticsParamType,
- perPage: 10000,
- });
- return data.saved_objects.map((savedObject) => toClientResponse(savedObject));
+ return findAllParams(routeContext);
}
} catch (error) {
if (error.output?.statusCode === 404) {
@@ -94,6 +58,70 @@ export const getSyntheticsParamsRoute: SyntheticsRestApiRouteFactory<
},
});
+const isAnAdminUser = async (routeContext: RouteContext) => {
+ const { request, server } = routeContext;
+ const user = server.coreStart.security.authc.getCurrentUser(request);
+
+ const isSuperUser = user?.roles.includes('superuser');
+ const isAdmin = user?.roles.includes('kibana_admin');
+
+ const canSave =
+ (
+ await server.coreStart?.capabilities.resolveCapabilities(request, {
+ capabilityPath: 'uptime.*',
+ })
+ ).uptime.save ?? false;
+
+ return (isSuperUser || isAdmin) && canSave;
+};
+
+const getDecryptedParams = async ({ server, spaceId }: RouteContext, paramId?: string) => {
+ const encryptedSavedObjectsClient = server.encryptedSavedObjects.getClient();
+
+ if (paramId) {
+ const savedObject =
+ await encryptedSavedObjectsClient.getDecryptedAsInternalUser(
+ syntheticsParamType,
+ paramId,
+ { namespace: spaceId }
+ );
+ return toClientResponse(savedObject);
+ }
+ const finder =
+ await encryptedSavedObjectsClient.createPointInTimeFinderDecryptedAsInternalUser(
+ {
+ type: syntheticsParamType,
+ perPage: 1000,
+ namespaces: [spaceId],
+ }
+ );
+
+ const hits: Array> = [];
+ for await (const result of finder.find()) {
+ hits.push(...result.saved_objects);
+ }
+
+ void finder.close();
+
+ return hits.map((savedObject) => toClientResponse(savedObject));
+};
+
+const findAllParams = async ({ savedObjectsClient }: RouteContext) => {
+ const finder = savedObjectsClient.createPointInTimeFinder({
+ type: syntheticsParamType,
+ perPage: 1000,
+ });
+
+ const hits: Array> = [];
+ for await (const result of finder.find()) {
+ hits.push(...result.saved_objects);
+ }
+
+ void finder.close();
+
+ return hits.map((savedObject) => toClientResponse(savedObject));
+};
+
const toClientResponse = (
savedObject: SavedObject
) => {
diff --git a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.test.ts b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.test.ts
index b4dd34952c7a8..227fff690af53 100644
--- a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.test.ts
+++ b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.test.ts
@@ -21,6 +21,14 @@ describe('isValidUrl', () => {
it('returns true for valid URL', () => {
expect(isValidURL('https://elastic.co')).toBeTruthy();
});
+
+ it('returns skips validation vars', () => {
+ expect(isValidURL('${urlParam}')).toBeTruthy();
+ });
+
+ it('returns skips validation vars with http', () => {
+ expect(isValidURL('http://${urlParam}')).toBeTruthy();
+ });
});
describe('getUrlsField', () => {
diff --git a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts
index 0a3aa8295a94d..c67e7decbe984 100644
--- a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts
+++ b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts
@@ -8,6 +8,7 @@
import { omit, uniqBy } from 'lodash';
import { i18n } from '@kbn/i18n';
import { isValidNamespace } from '@kbn/fleet-plugin/common';
+import { hasNoParams } from '../../formatters/formatting_utils';
import { formatLocation } from '../../../../common/utils/location_formatter';
import {
BrowserFields,
@@ -408,6 +409,10 @@ export const getOptionalListField = (value?: string[] | string): string[] => {
* @returns `true` if `new URL` does not throw an error, `false` otherwise
*/
export const isValidURL = (url: string): boolean => {
+ if (!hasNoParams(url)) {
+ // this is done to avoid parsing urls with variables
+ return true;
+ }
try {
new URL(url);
return true;
diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts
index 584b992a0f61d..68aaf7bf9cf04 100644
--- a/x-pack/plugins/security_solution/common/constants.ts
+++ b/x-pack/plugins/security_solution/common/constants.ts
@@ -280,6 +280,8 @@ export const PINNED_EVENT_URL = '/api/pinned_event' as const;
export const SOURCERER_API_URL = '/internal/security_solution/sourcerer' as const;
export const RISK_SCORE_INDEX_STATUS_API_URL = '/internal/risk_score/index_status' as const;
+export const EVENT_GRAPH_VISUALIZATION_API = '/internal/cloud_security_posture/graph' as const;
+
/**
* Default signals index key for kibana.dev.yml
*/
diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts
index ffb9e9748d9c1..792b6352912b3 100644
--- a/x-pack/plugins/security_solution/common/experimental_features.ts
+++ b/x-pack/plugins/security_solution/common/experimental_features.ts
@@ -190,6 +190,11 @@ export const allowedExperimentalValues = Object.freeze({
*/
analyzerDatePickersAndSourcererDisabled: false,
+ /**
+ * Enables graph visualization in alerts flyout
+ */
+ graphVisualizationInFlyoutEnabled: false,
+
/**
* Enables an ability to customize Elastic prebuilt rules.
*
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview.test.tsx
new file mode 100644
index 0000000000000..22ac27eaa4e00
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview.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 { render } from '@testing-library/react';
+import React from 'react';
+import { TestProviders } from '../../../../common/mock';
+import { mockContextValue } from '../../shared/mocks/mock_context';
+import { DocumentDetailsContext } from '../../shared/context';
+import { GraphPreview, type GraphPreviewProps } from './graph_preview';
+import { GRAPH_PREVIEW_TEST_ID, GRAPH_PREVIEW_LOADING_TEST_ID } from './test_ids';
+
+const mockGraph = () => ;
+
+jest.mock('@kbn/cloud-security-posture-graph', () => {
+ return { Graph: mockGraph };
+});
+
+const renderGraphPreview = (contextValue: DocumentDetailsContext, props: GraphPreviewProps) =>
+ render(
+
+
+
+
+
+ );
+
+const ERROR_MESSAGE = 'An error is preventing this alert from being visualized.';
+
+describe('', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('shows graph preview correctly when data is loaded', async () => {
+ const graphProps = {
+ isLoading: false,
+ isError: false,
+ data: { nodes: [], edges: [] },
+ };
+
+ const { findByTestId } = renderGraphPreview(mockContextValue, graphProps);
+
+ // Using findByTestId to wait for the component to be rendered because it is a lazy loaded component
+ expect(await findByTestId(GRAPH_PREVIEW_TEST_ID)).toBeInTheDocument();
+ });
+
+ it('shows loading when data is loading', () => {
+ const graphProps = {
+ isLoading: true,
+ isError: false,
+ };
+
+ const { getByTestId } = renderGraphPreview(mockContextValue, graphProps);
+
+ expect(getByTestId(GRAPH_PREVIEW_LOADING_TEST_ID)).toBeInTheDocument();
+ });
+
+ it('shows error message when there is an error', () => {
+ const graphProps = {
+ isLoading: false,
+ isError: true,
+ };
+
+ const { getByText } = renderGraphPreview(mockContextValue, graphProps);
+
+ expect(getByText(ERROR_MESSAGE)).toBeInTheDocument();
+ });
+});
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview.tsx
new file mode 100644
index 0000000000000..c3c6d65c7e986
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview.tsx
@@ -0,0 +1,102 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+import React, { memo, useMemo } from 'react';
+import { EuiSkeletonText } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { css } from '@emotion/react';
+import { FormattedMessage } from '@kbn/i18n-react';
+import type {
+ NodeDataModel,
+ EdgeDataModel,
+} from '@kbn/cloud-security-posture-common/types/graph/latest';
+import { GRAPH_PREVIEW_TEST_ID, GRAPH_PREVIEW_LOADING_TEST_ID } from './test_ids';
+
+/**
+ * Props for the GraphPreview component.
+ */
+export interface GraphPreviewProps {
+ /**
+ * Indicates whether the graph is currently loading.
+ */
+ isLoading: boolean;
+
+ /**
+ * Indicates whether there was an error loading the graph.
+ */
+ isError: boolean;
+
+ /**
+ * Optional data for the graph, including nodes and edges.
+ */
+ data?: {
+ /**
+ * Array of node data models.
+ */
+ nodes: NodeDataModel[];
+
+ /**
+ * Array of edge data models.
+ */
+ edges: EdgeDataModel[];
+ };
+}
+
+const GraphLazy = React.lazy(() =>
+ import('@kbn/cloud-security-posture-graph').then((module) => ({ default: module.Graph }))
+);
+
+const LoadingComponent = () => (
+
+);
+
+/**
+ * Graph preview under Overview, Visualizations. It shows a graph without abilities to expand.
+ */
+export const GraphPreview: React.FC = memo(
+ ({ isLoading, isError, data }: GraphPreviewProps) => {
+ const memoizedNodes = useMemo(() => data?.nodes ?? [], [data?.nodes]);
+ const memoizedEdges = useMemo(() => data?.edges ?? [], [data?.edges]);
+
+ return isLoading ? (
+
+ ) : isError ? (
+
+ ) : (
+ }>
+
+
+ );
+ }
+);
+
+GraphPreview.displayName = 'GraphPreview';
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview_container.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview_container.test.tsx
new file mode 100644
index 0000000000000..6b30e2127a2f8
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview_container.test.tsx
@@ -0,0 +1,110 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { render } from '@testing-library/react';
+import { TestProviders } from '../../../../common/mock';
+import React from 'react';
+import { DocumentDetailsContext } from '../../shared/context';
+import { mockContextValue } from '../../shared/mocks/mock_context';
+import { GraphPreviewContainer } from './graph_preview_container';
+import { GRAPH_PREVIEW_TEST_ID } from './test_ids';
+import { useGraphPreview } from '../hooks/use_graph_preview';
+import { useFetchGraphData } from '../hooks/use_fetch_graph_data';
+
+import {
+ EXPANDABLE_PANEL_CONTENT_TEST_ID,
+ EXPANDABLE_PANEL_HEADER_TITLE_ICON_TEST_ID,
+ EXPANDABLE_PANEL_HEADER_TITLE_LINK_TEST_ID,
+ EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID,
+ EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID,
+} from '@kbn/security-solution-common';
+
+jest.mock('../hooks/use_graph_preview');
+jest.mock('../hooks/use_fetch_graph_data', () => ({
+ useFetchGraphData: jest.fn(),
+}));
+const mockUseFetchGraphData = useFetchGraphData as jest.Mock;
+
+const mockUseUiSetting = jest.fn().mockReturnValue([false]);
+jest.mock('@kbn/kibana-react-plugin/public', () => {
+ const original = jest.requireActual('@kbn/kibana-react-plugin/public');
+ return {
+ ...original,
+ useUiSetting$: () => mockUseUiSetting(),
+ };
+});
+
+const mockGraph = () => ;
+
+jest.mock('@kbn/cloud-security-posture-graph', () => {
+ return { Graph: mockGraph };
+});
+
+const renderGraphPreview = (context = mockContextValue) =>
+ render(
+
+
+
+
+
+ );
+
+describe('', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('should render component and link in header', async () => {
+ mockUseFetchGraphData.mockReturnValue({
+ isLoading: false,
+ isError: false,
+ data: { nodes: [], edges: [] },
+ });
+
+ (useGraphPreview as jest.Mock).mockReturnValue({
+ isAuditLog: true,
+ });
+
+ const { getByTestId, queryByTestId, findByTestId } = renderGraphPreview();
+
+ // Using findByTestId to wait for the component to be rendered because it is a lazy loaded component
+ expect(await findByTestId(GRAPH_PREVIEW_TEST_ID)).toBeInTheDocument();
+ expect(
+ queryByTestId(EXPANDABLE_PANEL_HEADER_TITLE_LINK_TEST_ID(GRAPH_PREVIEW_TEST_ID))
+ ).not.toBeInTheDocument();
+ expect(
+ queryByTestId(EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID(GRAPH_PREVIEW_TEST_ID))
+ ).not.toBeInTheDocument();
+ expect(
+ getByTestId(EXPANDABLE_PANEL_HEADER_TITLE_ICON_TEST_ID(GRAPH_PREVIEW_TEST_ID))
+ ).toBeInTheDocument();
+ expect(
+ getByTestId(EXPANDABLE_PANEL_CONTENT_TEST_ID(GRAPH_PREVIEW_TEST_ID))
+ ).toBeInTheDocument();
+ expect(
+ getByTestId(EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID(GRAPH_PREVIEW_TEST_ID))
+ ).toBeInTheDocument();
+ });
+
+ it('should render error message and text in header', () => {
+ mockUseFetchGraphData.mockReturnValue({
+ isLoading: false,
+ isError: false,
+ data: undefined,
+ });
+
+ (useGraphPreview as jest.Mock).mockReturnValue({
+ isAuditLog: false,
+ });
+
+ const { getByTestId } = renderGraphPreview();
+
+ expect(
+ getByTestId(EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID(GRAPH_PREVIEW_TEST_ID))
+ ).toBeInTheDocument();
+ });
+});
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview_container.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview_container.tsx
new file mode 100644
index 0000000000000..1bc6a8dd7e547
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview_container.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 React from 'react';
+import { FormattedMessage } from '@kbn/i18n-react';
+import { ExpandablePanel } from '@kbn/security-solution-common';
+import { useDocumentDetailsContext } from '../../shared/context';
+import { GRAPH_PREVIEW_TEST_ID } from './test_ids';
+import { GraphPreview } from './graph_preview';
+import { useFetchGraphData } from '../hooks/use_fetch_graph_data';
+import { useGraphPreview } from '../hooks/use_graph_preview';
+
+const DEFAULT_FROM = 'now-60d/d';
+const DEFAULT_TO = 'now/d';
+
+/**
+ * Graph preview under Overview, Visualizations. It shows a graph representation of entities.
+ */
+export const GraphPreviewContainer: React.FC = () => {
+ const { dataAsNestedObject, getFieldsData } = useDocumentDetailsContext();
+
+ const { eventIds } = useGraphPreview({
+ getFieldsData,
+ ecsData: dataAsNestedObject,
+ });
+
+ // TODO: default start and end might not capture the original event
+ const graphFetchQuery = useFetchGraphData({
+ req: {
+ query: {
+ actorIds: [],
+ eventIds,
+ start: DEFAULT_FROM,
+ end: DEFAULT_TO,
+ },
+ },
+ });
+
+ return (
+
+ ),
+ iconType: 'indexMapping',
+ }}
+ data-test-subj={GRAPH_PREVIEW_TEST_ID}
+ content={
+ !graphFetchQuery.isLoading && !graphFetchQuery.isError
+ ? {
+ paddingSize: 'none',
+ }
+ : undefined
+ }
+ >
+
+
+ );
+};
+
+GraphPreviewContainer.displayName = 'GraphPreviewContainer';
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/test_ids.ts b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/test_ids.ts
index e0d8bc6db0f5c..e649c578bf487 100644
--- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/test_ids.ts
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/test_ids.ts
@@ -178,6 +178,9 @@ export const SESSION_PREVIEW_TEST_ID = `${PREFIX}SessionPreview` as const;
export const SESSION_PREVIEW_RULE_DETAILS_LINK_TEST_ID =
`${SESSION_PREVIEW_TEST_ID}RuleDetailsLink` as const;
+export const GRAPH_PREVIEW_TEST_ID = `${PREFIX}GraphPreview` as const;
+export const GRAPH_PREVIEW_LOADING_TEST_ID = `${GRAPH_PREVIEW_TEST_ID}Loading` as const;
+
/* Response section */
const RESPONSE_TEST_ID = `${PREFIX}Response` as const;
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/visualizations_section.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/visualizations_section.test.tsx
index 9af61e21fb67d..3aeb7d30f8e48 100644
--- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/visualizations_section.test.tsx
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/visualizations_section.test.tsx
@@ -11,6 +11,7 @@ import { render } from '@testing-library/react';
import {
ANALYZER_PREVIEW_TEST_ID,
SESSION_PREVIEW_TEST_ID,
+ GRAPH_PREVIEW_TEST_ID,
VISUALIZATIONS_SECTION_CONTENT_TEST_ID,
VISUALIZATIONS_SECTION_HEADER_TEST_ID,
} from './test_ids';
@@ -24,6 +25,9 @@ import { TestProvider } from '@kbn/expandable-flyout/src/test/provider';
import { useExpandSection } from '../hooks/use_expand_section';
import { useInvestigateInTimeline } from '../../../../detections/components/alerts_table/timeline_actions/use_investigate_in_timeline';
import { useIsInvestigateInResolverActionEnabled } from '../../../../detections/components/alerts_table/timeline_actions/investigate_in_resolver';
+import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features';
+import { useGraphPreview } from '../hooks/use_graph_preview';
+import { useFetchGraphData } from '../hooks/use_fetch_graph_data';
jest.mock('../hooks/use_expand_section');
jest.mock('../../shared/hooks/use_alert_prevalence_from_process_tree', () => ({
@@ -49,6 +53,11 @@ jest.mock(
jest.mock(
'../../../../detections/components/alerts_table/timeline_actions/investigate_in_resolver'
);
+jest.mock('../../../../common/hooks/use_experimental_features', () => ({
+ useIsExperimentalFeatureEnabled: jest.fn(),
+}));
+
+const useIsExperimentalFeatureEnabledMock = useIsExperimentalFeatureEnabled as jest.Mock;
const mockUseUiSetting = jest.fn().mockReturnValue([false]);
jest.mock('@kbn/kibana-react-plugin/public', () => {
@@ -58,6 +67,15 @@ jest.mock('@kbn/kibana-react-plugin/public', () => {
useUiSetting$: () => mockUseUiSetting(),
};
});
+jest.mock('../hooks/use_graph_preview');
+
+const mockUseGraphPreview = useGraphPreview as jest.Mock;
+
+jest.mock('../hooks/use_fetch_graph_data', () => ({
+ useFetchGraphData: jest.fn(),
+}));
+
+const mockUseFetchGraphData = useFetchGraphData as jest.Mock;
const panelContextValue = {
...mockContextValue,
@@ -84,6 +102,17 @@ describe('', () => {
alertIds: undefined,
statsNodes: undefined,
});
+ mockUseGraphPreview.mockReturnValue({
+ isAuditLog: true,
+ });
+ mockUseFetchGraphData.mockReturnValue({
+ isLoading: false,
+ isError: false,
+ data: {
+ nodes: [],
+ edges: [],
+ },
+ });
});
it('should render visualizations component', () => {
@@ -107,11 +136,22 @@ describe('', () => {
});
(useIsInvestigateInResolverActionEnabled as jest.Mock).mockReturnValue(true);
(useExpandSection as jest.Mock).mockReturnValue(true);
+ useIsExperimentalFeatureEnabledMock.mockReturnValue(false);
- const { getByTestId } = renderVisualizationsSection();
+ const { getByTestId, queryByTestId } = renderVisualizationsSection();
expect(getByTestId(VISUALIZATIONS_SECTION_CONTENT_TEST_ID)).toBeVisible();
expect(getByTestId(`${SESSION_PREVIEW_TEST_ID}LeftSection`)).toBeInTheDocument();
expect(getByTestId(`${ANALYZER_PREVIEW_TEST_ID}LeftSection`)).toBeInTheDocument();
+ expect(queryByTestId(`${GRAPH_PREVIEW_TEST_ID}LeftSection`)).not.toBeInTheDocument();
+ });
+
+ it('should render the graph preview component if the feature is enabled', () => {
+ (useExpandSection as jest.Mock).mockReturnValue(true);
+ useIsExperimentalFeatureEnabledMock.mockReturnValue(true);
+
+ const { getByTestId } = renderVisualizationsSection();
+
+ expect(getByTestId(`${GRAPH_PREVIEW_TEST_ID}LeftSection`)).toBeInTheDocument();
});
});
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/visualizations_section.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/visualizations_section.tsx
index afb828ebdb4e8..c328036eece43 100644
--- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/visualizations_section.tsx
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/visualizations_section.tsx
@@ -13,6 +13,10 @@ import { AnalyzerPreviewContainer } from './analyzer_preview_container';
import { SessionPreviewContainer } from './session_preview_container';
import { ExpandableSection } from './expandable_section';
import { VISUALIZATIONS_TEST_ID } from './test_ids';
+import { GraphPreviewContainer } from './graph_preview_container';
+import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features';
+import { useDocumentDetailsContext } from '../../shared/context';
+import { useGraphPreview } from '../hooks/use_graph_preview';
const KEY = 'visualizations';
@@ -21,6 +25,17 @@ const KEY = 'visualizations';
*/
export const VisualizationsSection = memo(() => {
const expanded = useExpandSection({ title: KEY, defaultValue: false });
+ const graphVisualizationInFlyoutEnabled = useIsExperimentalFeatureEnabled(
+ 'graphVisualizationInFlyoutEnabled'
+ );
+
+ const { dataAsNestedObject, getFieldsData } = useDocumentDetailsContext();
+
+ // Decide whether to show the graph preview or not
+ const { isAuditLog: isGraphPreviewEnabled } = useGraphPreview({
+ getFieldsData,
+ ecsData: dataAsNestedObject,
+ });
return (
{
+ {graphVisualizationInFlyoutEnabled && isGraphPreviewEnabled && (
+ <>
+
+
+ >
+ )}
);
});
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/hooks/use_fetch_graph_data.ts b/x-pack/plugins/security_solution/public/flyout/document_details/right/hooks/use_fetch_graph_data.ts
new file mode 100644
index 0000000000000..2304cfb8d4fd2
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/hooks/use_fetch_graph_data.ts
@@ -0,0 +1,83 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license 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 {
+ GraphRequest,
+ GraphResponse,
+} from '@kbn/cloud-security-posture-common/types/graph/latest';
+import { EVENT_GRAPH_VISUALIZATION_API } from '../../../../../common/constants';
+import { useHttp } from '../../../../common/lib/kibana';
+
+/**
+ * Interface for the input parameters of the useFetchGraphData hook.
+ */
+export interface UseFetchGraphDataParams {
+ /**
+ * The request object containing the query parameters for the graph data.
+ */
+ req: GraphRequest;
+ /**
+ * Optional configuration options for the query.
+ */
+ options?: {
+ /**
+ * If false, the query will not automatically run.
+ * Defaults to true.
+ */
+ enabled?: boolean;
+ };
+}
+
+/**
+ * Interface for the result of the useFetchGraphData hook.
+ */
+export interface UseFetchGraphDataResult {
+ /**
+ * Indicates if the query is currently loading.
+ */
+ isLoading: boolean;
+ /**
+ * Indicates if there was an error during the query.
+ */
+ isError: boolean;
+ /**
+ * The data returned from the query.
+ */
+ data?: GraphResponse;
+}
+
+/**
+ * Hook to fetch event's graph visualization data.
+ *
+ * @param params - The input parameters for the hook.
+ * @returns The result of the hook.
+ */
+export const useFetchGraphData = ({
+ req,
+ options,
+}: UseFetchGraphDataParams): UseFetchGraphDataResult => {
+ const { actorIds, eventIds, start, end } = req.query;
+ const http = useHttp();
+
+ const { isLoading, isError, data } = useQuery(
+ ['useFetchGraphData', actorIds, eventIds, start, end],
+ () => {
+ return http.post(EVENT_GRAPH_VISUALIZATION_API, {
+ version: '1',
+ body: JSON.stringify(req),
+ });
+ },
+ options
+ );
+
+ return {
+ isLoading,
+ isError,
+ data,
+ };
+};
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/hooks/use_graph_preview.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/hooks/use_graph_preview.test.tsx
new file mode 100644
index 0000000000000..ff6118ec9b743
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/hooks/use_graph_preview.test.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 type { RenderHookResult } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react-hooks';
+import type { UseGraphPreviewParams, UseGraphPreviewResult } from './use_graph_preview';
+import { useGraphPreview } from './use_graph_preview';
+import type { GetFieldsData } from '../../shared/hooks/use_get_fields_data';
+import { mockFieldData } from '../../shared/mocks/mock_get_fields_data';
+
+describe('useGraphPreview', () => {
+ let hookResult: RenderHookResult;
+
+ it(`should return false when missing actor`, () => {
+ const getFieldsData: GetFieldsData = (field: string) => {
+ if (field === 'kibana.alert.original_event.id') {
+ return field;
+ }
+ return mockFieldData[field];
+ };
+
+ hookResult = renderHook((props: UseGraphPreviewParams) => useGraphPreview(props), {
+ initialProps: {
+ getFieldsData,
+ ecsData: {
+ _id: 'id',
+ event: {
+ action: ['action'],
+ },
+ },
+ },
+ });
+
+ expect(hookResult.result.current.isAuditLog).toEqual(false);
+ });
+
+ it(`should return false when missing event.action`, () => {
+ const getFieldsData: GetFieldsData = (field: string) => {
+ if (field === 'kibana.alert.original_event.id') {
+ return 'eventId';
+ } else if (field === 'actor.entity.id') {
+ return 'actorId';
+ }
+ return mockFieldData[field];
+ };
+
+ hookResult = renderHook((props: UseGraphPreviewParams) => useGraphPreview(props), {
+ initialProps: {
+ getFieldsData,
+ ecsData: {
+ _id: 'id',
+ },
+ },
+ });
+
+ expect(hookResult.result.current.isAuditLog).toEqual(false);
+ });
+
+ it(`should return false when missing original_event.id`, () => {
+ const getFieldsData: GetFieldsData = (field: string) => {
+ if (field === 'actor.entity.id') {
+ return 'actorId';
+ }
+ return mockFieldData[field];
+ };
+
+ hookResult = renderHook((props: UseGraphPreviewParams) => useGraphPreview(props), {
+ initialProps: {
+ getFieldsData,
+ ecsData: {
+ _id: 'id',
+ event: {
+ action: ['action'],
+ },
+ },
+ },
+ });
+
+ expect(hookResult.result.current.isAuditLog).toEqual(false);
+ });
+
+ it(`should return true when alert is has graph preview`, () => {
+ const getFieldsData: GetFieldsData = (field: string) => {
+ if (field === 'kibana.alert.original_event.id') {
+ return 'eventId';
+ } else if (field === 'actor.entity.id') {
+ return 'actorId';
+ }
+
+ return mockFieldData[field];
+ };
+
+ hookResult = renderHook((props: UseGraphPreviewParams) => useGraphPreview(props), {
+ initialProps: {
+ getFieldsData,
+ ecsData: {
+ _id: 'id',
+ event: {
+ action: ['action'],
+ },
+ },
+ },
+ });
+
+ expect(hookResult.result.current.isAuditLog).toEqual(true);
+ });
+
+ it(`should return true when alert is has graph preview with multiple values`, () => {
+ const getFieldsData: GetFieldsData = (field: string) => {
+ if (field === 'kibana.alert.original_event.id') {
+ return ['id1', 'id2'];
+ } else if (field === 'actor.entity.id') {
+ return ['actorId1', 'actorId2'];
+ }
+
+ return mockFieldData[field];
+ };
+
+ hookResult = renderHook((props: UseGraphPreviewParams) => useGraphPreview(props), {
+ initialProps: {
+ getFieldsData,
+ ecsData: {
+ _id: 'id',
+ event: {
+ action: ['action1', 'action2'],
+ },
+ },
+ },
+ });
+
+ expect(hookResult.result.current.isAuditLog).toEqual(true);
+ });
+});
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/hooks/use_graph_preview.ts b/x-pack/plugins/security_solution/public/flyout/document_details/right/hooks/use_graph_preview.ts
new file mode 100644
index 0000000000000..d833c0aa86dbc
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/hooks/use_graph_preview.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 type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs';
+import { get } from 'lodash/fp';
+import type { GetFieldsData } from '../../shared/hooks/use_get_fields_data';
+import { getFieldArray } from '../../shared/utils';
+
+export interface UseGraphPreviewParams {
+ /**
+ * Retrieves searchHit values for the provided field
+ */
+ getFieldsData: GetFieldsData;
+
+ /**
+ * An object with top level fields from the ECS object
+ */
+ ecsData: Ecs;
+}
+/**
+ * Interface for the result of the useGraphPreview hook
+ */
+export interface UseGraphPreviewResult {
+ /**
+ * Array of event IDs associated with the alert
+ */
+ eventIds: string[];
+
+ /**
+ * Array of actor entity IDs associated with the alert
+ */
+ actorIds: string[];
+
+ /**
+ * Action associated with the event
+ */
+ action: string | undefined;
+
+ /**
+ * Boolean indicating if the event is an audit log (contains event ids, actor ids and action)
+ */
+ isAuditLog: boolean;
+}
+
+/**
+ * Hook that returns the graph view configuration if the graph view is available for the alert
+ */
+export const useGraphPreview = ({
+ getFieldsData,
+ ecsData,
+}: UseGraphPreviewParams): UseGraphPreviewResult => {
+ const originalEventId = getFieldsData('kibana.alert.original_event.id');
+ const eventId = getFieldsData('event.id');
+ const eventIds = originalEventId ? getFieldArray(originalEventId) : getFieldArray(eventId);
+
+ const actorIds = getFieldArray(getFieldsData('actor.entity.id'));
+ const action = get(['event', 'action'], ecsData);
+ const isAuditLog = actorIds.length > 0 && action?.length > 0 && eventIds.length > 0;
+
+ return { eventIds, actorIds, action, isAuditLog };
+};
diff --git a/x-pack/plugins/security_solution/tsconfig.json b/x-pack/plugins/security_solution/tsconfig.json
index 2b11529ea4d72..15d082d32edda 100644
--- a/x-pack/plugins/security_solution/tsconfig.json
+++ b/x-pack/plugins/security_solution/tsconfig.json
@@ -220,6 +220,7 @@
"@kbn/cloud-security-posture",
"@kbn/security-solution-distribution-bar",
"@kbn/cloud-security-posture-common",
+ "@kbn/cloud-security-posture-graph",
"@kbn/presentation-publishing",
"@kbn/entityManager-plugin",
"@kbn/entities-schema",
diff --git a/x-pack/test/api_integration/apis/synthetics/add_edit_params.ts b/x-pack/test/api_integration/apis/synthetics/add_edit_params.ts
index 4de02eb80b30c..7b27aaa621f46 100644
--- a/x-pack/test/api_integration/apis/synthetics/add_edit_params.ts
+++ b/x-pack/test/api_integration/apis/synthetics/add_edit_params.ts
@@ -10,6 +10,7 @@ import { pick } from 'lodash';
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
import expect from '@kbn/expect';
import { syntheticsParamType } from '@kbn/synthetics-plugin/common/types/saved_objects';
+import { SyntheticsMonitorTestService } from './services/synthetics_monitor_test_service';
import { FtrProviderContext } from '../../ftr_provider_context';
import { PrivateLocationTestService } from './services/private_location_test_service';
@@ -21,12 +22,15 @@ export default function ({ getService }: FtrProviderContext) {
describe('AddEditParams', function () {
this.tags('skipCloud');
const supertestAPI = getService('supertest');
+ const supertestWithoutAuth = getService('supertestWithoutAuth');
+
const kServer = getService('kibanaServer');
const testParam = {
key: 'test',
value: 'test',
};
const testPrivateLocations = new PrivateLocationTestService(getService);
+ const monitorTestService = new SyntheticsMonitorTestService(getService);
before(async () => {
await testPrivateLocations.installSyntheticsPackage();
@@ -93,6 +97,12 @@ export default function ({ getService }: FtrProviderContext) {
const param = getResponse.body[0];
assertHas(param, testParam);
+ await supertestAPI
+ .put(SYNTHETICS_API_URLS.PARAMS + '/' + param.id)
+ .set('kbn-xsrf', 'true')
+ .send({})
+ .expect(400);
+
await supertestAPI
.put(SYNTHETICS_API_URLS.PARAMS + '/' + param.id)
.set('kbn-xsrf', 'true')
@@ -107,6 +117,55 @@ export default function ({ getService }: FtrProviderContext) {
assertHas(actualUpdatedParam, expectedUpdatedParam);
});
+ it('handles partial editing a param', async () => {
+ const newParam = {
+ key: 'testUpdated',
+ value: 'testUpdated',
+ tags: ['a tag'],
+ description: 'test description',
+ };
+
+ const response = await supertestAPI
+ .post(SYNTHETICS_API_URLS.PARAMS)
+ .set('kbn-xsrf', 'true')
+ .send(newParam)
+ .expect(200);
+ const paramId = response.body.id;
+
+ const getResponse = await supertestAPI
+ .get(SYNTHETICS_API_URLS.PARAMS + '/' + paramId)
+ .set('kbn-xsrf', 'true')
+ .expect(200);
+ assertHas(getResponse.body, newParam);
+
+ await supertestAPI
+ .put(SYNTHETICS_API_URLS.PARAMS + '/' + paramId)
+ .set('kbn-xsrf', 'true')
+ .send({
+ key: 'testUpdated',
+ })
+ .expect(200);
+
+ await supertestAPI
+ .put(SYNTHETICS_API_URLS.PARAMS + '/' + paramId)
+ .set('kbn-xsrf', 'true')
+ .send({
+ key: 'testUpdatedAgain',
+ value: 'testUpdatedAgain',
+ })
+ .expect(200);
+
+ const updatedGetResponse = await supertestAPI
+ .get(SYNTHETICS_API_URLS.PARAMS + '/' + paramId)
+ .set('kbn-xsrf', 'true')
+ .expect(200);
+ assertHas(updatedGetResponse.body, {
+ ...newParam,
+ key: 'testUpdatedAgain',
+ value: 'testUpdatedAgain',
+ });
+ });
+
it('handles spaces', async () => {
const SPACE_ID = `test-space-${uuidv4()}`;
const SPACE_NAME = `test-space-name ${uuidv4()}`;
@@ -277,5 +336,22 @@ export default function ({ getService }: FtrProviderContext) {
expect(getResponse.body[0].namespaces).eql(['*']);
assertHas(getResponse.body[0], testParam);
});
+
+ it('should not return values for non admin user', async () => {
+ const { username, password } = await monitorTestService.addsNewSpace();
+ const resp = await supertestWithoutAuth
+ .get(`${SYNTHETICS_API_URLS.PARAMS}`)
+ .auth(username, password)
+ .set('kbn-xsrf', 'true')
+ .send()
+ .expect(200);
+
+ const params = resp.body;
+ expect(params.length).to.eql(6);
+ params.forEach((param: any) => {
+ expect(param.value).to.eql(undefined);
+ expect(param.key).to.not.empty();
+ });
+ });
});
}
diff --git a/x-pack/test/cloud_security_posture_functional/config.ts b/x-pack/test/cloud_security_posture_functional/config.ts
index 28283fe427949..7e80788ffccfe 100644
--- a/x-pack/test/cloud_security_posture_functional/config.ts
+++ b/x-pack/test/cloud_security_posture_functional/config.ts
@@ -38,6 +38,9 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
* 1. release a new package to EPR
* 2. merge the updated version number change to kibana
*/
+ `--xpack.securitySolution.enableExperimental=${JSON.stringify([
+ 'graphVisualizationInFlyoutEnabled',
+ ])}`,
`--xpack.fleet.packages.0.name=cloud_security_posture`,
`--xpack.fleet.packages.0.version=${CLOUD_SECURITY_PLUGIN_VERSION}`,
// `--xpack.fleet.registryUrl=https://localhost:8080`,
diff --git a/x-pack/test/cloud_security_posture_functional/es_archives/logs_gcp_audit/data.json b/x-pack/test/cloud_security_posture_functional/es_archives/logs_gcp_audit/data.json
new file mode 100644
index 0000000000000..5e3d4cdfdffd5
--- /dev/null
+++ b/x-pack/test/cloud_security_posture_functional/es_archives/logs_gcp_audit/data.json
@@ -0,0 +1,634 @@
+{
+ "type": "doc",
+ "value": {
+ "data_stream": "logs-gcp.audit-default",
+ "id": "1",
+ "index": ".ds-logs-gcp.audit-default-2024.10.07-000001",
+ "source": {
+ "@timestamp": "2024-09-01T12:34:56.789Z",
+ "actor": {
+ "entity": {
+ "id": "admin@example.com"
+ }
+ },
+ "client": {
+ "user": {
+ "email": "admin@example.com"
+ }
+ },
+ "cloud": {
+ "project": {
+ "id": "your-project-id"
+ },
+ "provider": "gcp"
+ },
+ "ecs": {
+ "version": "8.11.0"
+ },
+ "event": {
+ "action": "google.iam.admin.v1.CreateRole",
+ "agent_id_status": "missing",
+ "category": [
+ "session",
+ "network",
+ "configuration"
+ ],
+ "id": "kabcd1234efgh5678",
+ "ingested": "2024-10-07T17:47:35Z",
+ "kind": "event",
+ "outcome": "success",
+ "provider": "activity",
+ "type": [
+ "end",
+ "access",
+ "allowed"
+ ]
+ },
+ "gcp": {
+ "audit": {
+ "authorization_info": [
+ {
+ "granted": true,
+ "permission": "iam.roles.create",
+ "resource": "projects/your-project-id"
+ }
+ ],
+ "logentry_operation": {
+ "id": "operation-0987654321"
+ },
+ "request": {
+ "@type": "type.googleapis.com/google.iam.admin.v1.CreateRoleRequest",
+ "parent": "projects/your-project-id",
+ "role": {
+ "description": "A custom role with specific permissions",
+ "includedPermissions": [
+ "resourcemanager.projects.get",
+ "resourcemanager.projects.list"
+ ],
+ "name": "projects/your-project-id/roles/customRole",
+ "title": "Custom Role"
+ },
+ "roleId": "customRole"
+ },
+ "resource_name": "projects/your-project-id/roles/customRole",
+ "response": {
+ "@type": "type.googleapis.com/google.iam.admin.v1.Role",
+ "description": "A custom role with specific permissions",
+ "includedPermissions": [
+ "resourcemanager.projects.get",
+ "resourcemanager.projects.list"
+ ],
+ "name": "projects/your-project-id/roles/customRole",
+ "stage": "GA",
+ "title": "Custom Role"
+ },
+ "type": "type.googleapis.com/google.cloud.audit.AuditLog"
+ }
+ },
+ "log": {
+ "level": "NOTICE",
+ "logger": "projects/your-project-id/logs/cloudaudit.googleapis.com%2Factivity"
+ },
+ "related": {
+ "ip": [
+ "10.0.0.1"
+ ],
+ "user": [
+ "admin@example.com"
+ ]
+ },
+ "service": {
+ "name": "iam.googleapis.com"
+ },
+ "source": {
+ "ip": "10.0.0.1"
+ },
+ "tags": [
+ "_geoip_database_unavailable_GeoLite2-City.mmdb",
+ "_geoip_database_unavailable_GeoLite2-ASN.mmdb"
+ ],
+ "target": {
+ "entity": {
+ "id": "projects/your-project-id/roles/customRole"
+ }
+ },
+ "user_agent": {
+ "device": {
+ "name": "Other"
+ },
+ "name": "Other",
+ "original": "google-cloud-sdk/324.0.0"
+ }
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "data_stream": "logs-gcp.audit-default",
+ "id": "2",
+ "index": ".ds-logs-gcp.audit-default-2024.10.07-000001",
+ "source": {
+ "@timestamp": "2024-09-01T12:34:56.789Z",
+ "actor": {
+ "entity": {
+ "id": "admin2@example.com"
+ }
+ },
+ "client": {
+ "user": {
+ "email": "admin2@example.com"
+ }
+ },
+ "cloud": {
+ "project": {
+ "id": "your-project-id"
+ },
+ "provider": "gcp"
+ },
+ "ecs": {
+ "version": "8.11.0"
+ },
+ "event": {
+ "action": "google.iam.admin.v1.CreateRole",
+ "agent_id_status": "missing",
+ "category": [
+ "session",
+ "network",
+ "configuration"
+ ],
+ "id": "failed-event",
+ "ingested": "2024-10-07T17:47:35Z",
+ "kind": "event",
+ "outcome": "failed",
+ "provider": "activity",
+ "type": [
+ "end",
+ "access",
+ "allowed"
+ ]
+ },
+ "gcp": {
+ "audit": {
+ "authorization_info": [
+ {
+ "granted": true,
+ "permission": "iam.roles.create",
+ "resource": "projects/your-project-id"
+ }
+ ],
+ "logentry_operation": {
+ "id": "operation-0987654321"
+ },
+ "request": {
+ "@type": "type.googleapis.com/google.iam.admin.v1.CreateRoleRequest",
+ "parent": "projects/your-project-id",
+ "role": {
+ "description": "A custom role with specific permissions",
+ "includedPermissions": [
+ "resourcemanager.projects.get",
+ "resourcemanager.projects.list"
+ ],
+ "name": "projects/your-project-id/roles/customRole",
+ "title": "Custom Role"
+ },
+ "roleId": "customRole"
+ },
+ "resource_name": "projects/your-project-id/roles/customRole",
+ "response": {
+ "@type": "type.googleapis.com/google.iam.admin.v1.Role",
+ "description": "A custom role with specific permissions",
+ "includedPermissions": [
+ "resourcemanager.projects.get",
+ "resourcemanager.projects.list"
+ ],
+ "name": "projects/your-project-id/roles/customRole",
+ "stage": "GA",
+ "title": "Custom Role"
+ },
+ "type": "type.googleapis.com/google.cloud.audit.AuditLog"
+ }
+ },
+ "log": {
+ "level": "NOTICE",
+ "logger": "projects/your-project-id/logs/cloudaudit.googleapis.com%2Factivity"
+ },
+ "related": {
+ "ip": [
+ "10.0.0.1"
+ ],
+ "user": [
+ "admin2@example.com"
+ ]
+ },
+ "service": {
+ "name": "iam.googleapis.com"
+ },
+ "source": {
+ "ip": "10.0.0.1"
+ },
+ "tags": [
+ "_geoip_database_unavailable_GeoLite2-City.mmdb",
+ "_geoip_database_unavailable_GeoLite2-ASN.mmdb"
+ ],
+ "target": {
+ "entity": {
+ "id": "projects/your-project-id/roles/customRole"
+ }
+ },
+ "user_agent": {
+ "device": {
+ "name": "Other"
+ },
+ "name": "Other",
+ "original": "google-cloud-sdk/324.0.0"
+ }
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "data_stream": "logs-gcp.audit-default",
+ "id": "3",
+ "index": ".ds-logs-gcp.audit-default-2024.10.07-000001",
+ "source": {
+ "@timestamp": "2024-09-01T12:34:56.789Z",
+ "actor": {
+ "entity": {
+ "id": "admin3@example.com"
+ }
+ },
+ "client": {
+ "user": {
+ "email": "admin3@example.com"
+ }
+ },
+ "cloud": {
+ "project": {
+ "id": "your-project-id"
+ },
+ "provider": "gcp"
+ },
+ "ecs": {
+ "version": "8.11.0"
+ },
+ "event": {
+ "action": "google.iam.admin.v1.CreateRole",
+ "agent_id_status": "missing",
+ "category": [
+ "session",
+ "network",
+ "configuration"
+ ],
+ "id": "grouped-event1",
+ "ingested": "2024-10-07T17:47:35Z",
+ "kind": "event",
+ "outcome": "failed",
+ "provider": "activity",
+ "type": [
+ "end",
+ "access",
+ "allowed"
+ ]
+ },
+ "gcp": {
+ "audit": {
+ "authorization_info": [
+ {
+ "granted": true,
+ "permission": "iam.roles.create",
+ "resource": "projects/your-project-id"
+ }
+ ],
+ "logentry_operation": {
+ "id": "operation-0987654321"
+ },
+ "request": {
+ "@type": "type.googleapis.com/google.iam.admin.v1.CreateRoleRequest",
+ "parent": "projects/your-project-id",
+ "role": {
+ "description": "A custom role with specific permissions",
+ "includedPermissions": [
+ "resourcemanager.projects.get",
+ "resourcemanager.projects.list"
+ ],
+ "name": "projects/your-project-id/roles/customRole",
+ "title": "Custom Role"
+ },
+ "roleId": "customRole"
+ },
+ "resource_name": "projects/your-project-id/roles/customRole",
+ "response": {
+ "@type": "type.googleapis.com/google.iam.admin.v1.Role",
+ "description": "A custom role with specific permissions",
+ "includedPermissions": [
+ "resourcemanager.projects.get",
+ "resourcemanager.projects.list"
+ ],
+ "name": "projects/your-project-id/roles/customRole",
+ "stage": "GA",
+ "title": "Custom Role"
+ },
+ "type": "type.googleapis.com/google.cloud.audit.AuditLog"
+ }
+ },
+ "log": {
+ "level": "NOTICE",
+ "logger": "projects/your-project-id/logs/cloudaudit.googleapis.com%2Factivity"
+ },
+ "related": {
+ "ip": [
+ "10.0.0.1"
+ ],
+ "user": [
+ "admin3@example.com"
+ ]
+ },
+ "service": {
+ "name": "iam.googleapis.com"
+ },
+ "source": {
+ "ip": "10.0.0.1"
+ },
+ "tags": [
+ "_geoip_database_unavailable_GeoLite2-City.mmdb",
+ "_geoip_database_unavailable_GeoLite2-ASN.mmdb"
+ ],
+ "target": {
+ "entity": {
+ "id": "projects/your-project-id/roles/customRole"
+ }
+ },
+ "user_agent": {
+ "device": {
+ "name": "Other"
+ },
+ "name": "Other",
+ "original": "google-cloud-sdk/324.0.0"
+ }
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "data_stream": "logs-gcp.audit-default",
+ "id": "4",
+ "index": ".ds-logs-gcp.audit-default-2024.10.07-000001",
+ "source": {
+ "@timestamp": "2024-09-01T12:34:56.789Z",
+ "actor": {
+ "entity": {
+ "id": "admin3@example.com"
+ }
+ },
+ "client": {
+ "user": {
+ "email": "admin3@example.com"
+ }
+ },
+ "cloud": {
+ "project": {
+ "id": "your-project-id"
+ },
+ "provider": "gcp"
+ },
+ "ecs": {
+ "version": "8.11.0"
+ },
+ "event": {
+ "action": "google.iam.admin.v1.CreateRole",
+ "agent_id_status": "missing",
+ "category": [
+ "session",
+ "network",
+ "configuration"
+ ],
+ "id": "grouped-event2",
+ "ingested": "2024-10-07T17:47:35Z",
+ "kind": "event",
+ "outcome": "success",
+ "provider": "activity",
+ "type": [
+ "end",
+ "access",
+ "allowed"
+ ]
+ },
+ "gcp": {
+ "audit": {
+ "authorization_info": [
+ {
+ "granted": true,
+ "permission": "iam.roles.create",
+ "resource": "projects/your-project-id"
+ }
+ ],
+ "logentry_operation": {
+ "id": "operation-0987654321"
+ },
+ "request": {
+ "@type": "type.googleapis.com/google.iam.admin.v1.CreateRoleRequest",
+ "parent": "projects/your-project-id",
+ "role": {
+ "description": "A custom role with specific permissions",
+ "includedPermissions": [
+ "resourcemanager.projects.get",
+ "resourcemanager.projects.list"
+ ],
+ "name": "projects/your-project-id/roles/customRole",
+ "title": "Custom Role"
+ },
+ "roleId": "customRole"
+ },
+ "resource_name": "projects/your-project-id/roles/customRole",
+ "response": {
+ "@type": "type.googleapis.com/google.iam.admin.v1.Role",
+ "description": "A custom role with specific permissions",
+ "includedPermissions": [
+ "resourcemanager.projects.get",
+ "resourcemanager.projects.list"
+ ],
+ "name": "projects/your-project-id/roles/customRole",
+ "stage": "GA",
+ "title": "Custom Role"
+ },
+ "type": "type.googleapis.com/google.cloud.audit.AuditLog"
+ }
+ },
+ "log": {
+ "level": "NOTICE",
+ "logger": "projects/your-project-id/logs/cloudaudit.googleapis.com%2Factivity"
+ },
+ "related": {
+ "ip": [
+ "10.0.0.1"
+ ],
+ "user": [
+ "admin3@example.com"
+ ]
+ },
+ "service": {
+ "name": "iam.googleapis.com"
+ },
+ "source": {
+ "ip": "10.0.0.1"
+ },
+ "tags": [
+ "_geoip_database_unavailable_GeoLite2-City.mmdb",
+ "_geoip_database_unavailable_GeoLite2-ASN.mmdb"
+ ],
+ "target": {
+ "entity": {
+ "id": "projects/your-project-id/roles/customRole"
+ }
+ },
+ "user_agent": {
+ "device": {
+ "name": "Other"
+ },
+ "name": "Other",
+ "original": "google-cloud-sdk/324.0.0"
+ }
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "data_stream": "logs-gcp.audit-default",
+ "id": "5",
+ "index": ".ds-logs-gcp.audit-default-2024.10.07-000001",
+ "source": {
+ "@timestamp": "2024-09-01T12:34:56.789Z",
+ "actor": {
+ "entity": {
+ "id": "admin4@example.com"
+ }
+ },
+ "client": {
+ "user": {
+ "email": "admin4@example.com"
+ }
+ },
+ "cloud": {
+ "project": {
+ "id": "your-project-id"
+ },
+ "provider": "gcp"
+ },
+ "ecs": {
+ "version": "8.11.0"
+ },
+ "event": {
+ "action": "google.iam.admin.v1.CreateRole",
+ "agent_id_status": "missing",
+ "category": [
+ "session",
+ "network",
+ "configuration"
+ ],
+ "id": "host-event",
+ "ingested": "2024-10-07T17:47:35Z",
+ "kind": "event",
+ "outcome": "success",
+ "provider": "activity",
+ "type": [
+ "end",
+ "access",
+ "allowed"
+ ]
+ },
+ "gcp": {
+ "audit": {
+ "authorization_info": [
+ {
+ "granted": true,
+ "permission": "iam.roles.create",
+ "resource": "projects/your-project-id"
+ }
+ ],
+ "logentry_operation": {
+ "id": "operation-0987654321"
+ },
+ "request": {
+ "@type": "type.googleapis.com/google.iam.admin.v1.CreateRoleRequest",
+ "parent": "projects/your-project-id",
+ "role": {
+ "description": "A custom role with specific permissions",
+ "includedPermissions": [
+ "resourcemanager.projects.get",
+ "resourcemanager.projects.list"
+ ],
+ "name": "projects/your-project-id/roles/customRole",
+ "title": "Custom Role"
+ },
+ "roleId": "customRole"
+ },
+ "resource_name": "projects/your-project-id/roles/customRole",
+ "response": {
+ "@type": "type.googleapis.com/google.iam.admin.v1.Role",
+ "description": "A custom role with specific permissions",
+ "includedPermissions": [
+ "resourcemanager.projects.get",
+ "resourcemanager.projects.list"
+ ],
+ "name": "projects/your-project-id/roles/customRole",
+ "stage": "GA",
+ "title": "Custom Role"
+ },
+ "type": "type.googleapis.com/google.cloud.audit.AuditLog"
+ }
+ },
+ "host": {
+ "hostname": "host1.example.com",
+ "name": "host1.example.com",
+ "ip": "192.168.1.1",
+ "os": {
+ "name": "Linux",
+ "version": "5.4.0-42-generic"
+ }
+ },
+ "log": {
+ "level": "NOTICE",
+ "logger": "projects/your-project-id/logs/cloudaudit.googleapis.com%2Factivity"
+ },
+ "related": {
+ "ip": [
+ "10.0.0.1"
+ ],
+ "user": [
+ "admin4@example.com"
+ ]
+ },
+ "service": {
+ "name": "iam.googleapis.com"
+ },
+ "source": {
+ "ip": "10.0.0.1"
+ },
+ "tags": [
+ "_geoip_database_unavailable_GeoLite2-City.mmdb",
+ "_geoip_database_unavailable_GeoLite2-ASN.mmdb"
+ ],
+ "target": {
+ "entity": {
+ "id": "projects/your-project-id/roles/customRole"
+ }
+ },
+ "user_agent": {
+ "device": {
+ "name": "Other"
+ },
+ "name": "Other",
+ "original": "google-cloud-sdk/324.0.0"
+ }
+ }
+ }
+}
+
diff --git a/x-pack/test/cloud_security_posture_functional/es_archives/logs_gcp_audit/mappings.json b/x-pack/test/cloud_security_posture_functional/es_archives/logs_gcp_audit/mappings.json
new file mode 100644
index 0000000000000..085fc6d11d475
--- /dev/null
+++ b/x-pack/test/cloud_security_posture_functional/es_archives/logs_gcp_audit/mappings.json
@@ -0,0 +1,628 @@
+{
+ "type": "data_stream",
+ "value": {
+ "data_stream": "logs-gcp.audit-default",
+ "template": {
+ "_meta": {
+ "managed": true,
+ "managed_by": "fleet",
+ "package": {
+ "name": "gcp"
+ }
+ },
+ "data_stream": {
+ "allow_custom_routing": false,
+ "hidden": false
+ },
+ "ignore_missing_component_templates": [
+ "logs-gcp.audit@custom"
+ ],
+ "index_patterns": [
+ "logs-gcp.audit-*"
+ ],
+ "name": "logs-gcp.audit",
+ "priority": 200,
+ "template": {
+ "mappings": {
+ "_meta": {
+ "managed": true,
+ "managed_by": "fleet",
+ "package": {
+ "name": "gcp"
+ }
+ },
+ "date_detection": false,
+ "dynamic_templates": [
+ {
+ "ecs_message_match_only_text": {
+ "mapping": {
+ "type": "match_only_text"
+ },
+ "path_match": [
+ "message",
+ "*.message"
+ ],
+ "unmatch_mapping_type": "object"
+ }
+ },
+ {
+ "ecs_non_indexed_keyword": {
+ "mapping": {
+ "doc_values": false,
+ "index": false,
+ "type": "keyword"
+ },
+ "path_match": [
+ "*event.original"
+ ]
+ }
+ },
+ {
+ "ecs_non_indexed_long": {
+ "mapping": {
+ "doc_values": false,
+ "index": false,
+ "type": "long"
+ },
+ "path_match": [
+ "*.x509.public_key_exponent"
+ ]
+ }
+ },
+ {
+ "ecs_ip": {
+ "mapping": {
+ "type": "ip"
+ },
+ "match_mapping_type": "string",
+ "path_match": [
+ "ip",
+ "*.ip",
+ "*_ip"
+ ]
+ }
+ },
+ {
+ "ecs_wildcard": {
+ "mapping": {
+ "type": "wildcard"
+ },
+ "path_match": [
+ "*.io.text",
+ "*.message_id",
+ "*registry.data.strings",
+ "*url.path"
+ ],
+ "unmatch_mapping_type": "object"
+ }
+ },
+ {
+ "ecs_path_match_wildcard_and_match_only_text": {
+ "mapping": {
+ "fields": {
+ "text": {
+ "type": "match_only_text"
+ }
+ },
+ "type": "wildcard"
+ },
+ "path_match": [
+ "*.body.content",
+ "*url.full",
+ "*url.original"
+ ],
+ "unmatch_mapping_type": "object"
+ }
+ },
+ {
+ "ecs_match_wildcard_and_match_only_text": {
+ "mapping": {
+ "fields": {
+ "text": {
+ "type": "match_only_text"
+ }
+ },
+ "type": "wildcard"
+ },
+ "match": [
+ "*command_line",
+ "*stack_trace"
+ ],
+ "unmatch_mapping_type": "object"
+ }
+ },
+ {
+ "ecs_path_match_keyword_and_match_only_text": {
+ "mapping": {
+ "fields": {
+ "text": {
+ "type": "match_only_text"
+ }
+ },
+ "type": "keyword"
+ },
+ "path_match": [
+ "*.title",
+ "*.executable",
+ "*.name",
+ "*.working_directory",
+ "*.full_name",
+ "*file.path",
+ "*file.target_path",
+ "*os.full",
+ "*email.subject",
+ "*vulnerability.description",
+ "*user_agent.original"
+ ],
+ "unmatch_mapping_type": "object"
+ }
+ },
+ {
+ "ecs_date": {
+ "mapping": {
+ "type": "date"
+ },
+ "path_match": [
+ "*.timestamp",
+ "*_timestamp",
+ "*.not_after",
+ "*.not_before",
+ "*.accessed",
+ "created",
+ "*.created",
+ "*.installed",
+ "*.creation_date",
+ "*.ctime",
+ "*.mtime",
+ "ingested",
+ "*.ingested",
+ "*.start",
+ "*.end",
+ "*.indicator.first_seen",
+ "*.indicator.last_seen",
+ "*.indicator.modified_at",
+ "*threat.enrichments.matched.occurred"
+ ],
+ "unmatch_mapping_type": "object"
+ }
+ },
+ {
+ "ecs_path_match_float": {
+ "mapping": {
+ "type": "float"
+ },
+ "path_match": [
+ "*.score.*",
+ "*_score*"
+ ],
+ "path_unmatch": "*.version",
+ "unmatch_mapping_type": "object"
+ }
+ },
+ {
+ "ecs_usage_double_scaled_float": {
+ "mapping": {
+ "scaling_factor": 1000,
+ "type": "scaled_float"
+ },
+ "match_mapping_type": [
+ "double",
+ "long",
+ "string"
+ ],
+ "path_match": "*.usage"
+ }
+ },
+ {
+ "ecs_geo_point": {
+ "mapping": {
+ "type": "geo_point"
+ },
+ "path_match": [
+ "*.geo.location"
+ ]
+ }
+ },
+ {
+ "ecs_flattened": {
+ "mapping": {
+ "type": "flattened"
+ },
+ "match_mapping_type": "object",
+ "path_match": [
+ "*structured_data",
+ "*exports",
+ "*imports"
+ ]
+ }
+ },
+ {
+ "all_strings_to_keywords": {
+ "mapping": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "match_mapping_type": "string"
+ }
+ }
+ ],
+ "properties": {
+ "@timestamp": {
+ "ignore_malformed": false,
+ "type": "date"
+ },
+ "cloud": {
+ "properties": {
+ "image": {
+ "properties": {
+ "id": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ }
+ }
+ }
+ }
+ },
+ "data_stream": {
+ "properties": {
+ "dataset": {
+ "type": "constant_keyword"
+ },
+ "namespace": {
+ "type": "constant_keyword"
+ },
+ "type": {
+ "type": "constant_keyword"
+ }
+ }
+ },
+ "data_stream.dataset": {
+ "type": "constant_keyword"
+ },
+ "data_stream.namespace": {
+ "type": "constant_keyword"
+ },
+ "data_stream.type": {
+ "type": "constant_keyword",
+ "value": "logs"
+ },
+ "event": {
+ "properties": {
+ "agent_id_status": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "dataset": {
+ "type": "constant_keyword",
+ "value": "gcp.audit"
+ },
+ "ingested": {
+ "format": "strict_date_time_no_millis||strict_date_optional_time||epoch_millis",
+ "ignore_malformed": false,
+ "type": "date"
+ },
+ "module": {
+ "type": "constant_keyword",
+ "value": "gcp"
+ }
+ }
+ },
+ "gcp": {
+ "properties": {
+ "audit": {
+ "properties": {
+ "authentication_info": {
+ "properties": {
+ "authority_selector": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "principal_email": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "principal_subject": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "service_account_delegation_info": {
+ "type": "flattened"
+ },
+ "service_account_key_name": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "third_party_principal": {
+ "type": "flattened"
+ }
+ }
+ },
+ "authorization_info": {
+ "properties": {
+ "granted": {
+ "type": "boolean"
+ },
+ "permission": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "resource": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "resource_attributes": {
+ "properties": {
+ "name": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "service": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "type": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ }
+ }
+ }
+ },
+ "type": "nested"
+ },
+ "flattened": {
+ "type": "flattened"
+ },
+ "labels": {
+ "type": "flattened"
+ },
+ "logentry_operation": {
+ "properties": {
+ "first": {
+ "type": "boolean"
+ },
+ "id": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "last": {
+ "type": "boolean"
+ },
+ "producer": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ }
+ }
+ },
+ "metadata": {
+ "type": "flattened"
+ },
+ "method_name": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "num_response_items": {
+ "type": "long"
+ },
+ "policy_violation_info": {
+ "properties": {
+ "payload": {
+ "type": "flattened"
+ },
+ "resource_tags": {
+ "type": "flattened"
+ },
+ "resource_type": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "violations": {
+ "properties": {
+ "checkedValue": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "constraint": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "errorMessage": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "policyType": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ }
+ },
+ "type": "nested"
+ }
+ }
+ },
+ "request": {
+ "type": "flattened"
+ },
+ "request_metadata": {
+ "properties": {
+ "caller_ip": {
+ "type": "ip"
+ },
+ "caller_supplied_user_agent": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "raw": {
+ "properties": {
+ "caller_ip": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ }
+ }
+ }
+ }
+ },
+ "resource_location": {
+ "properties": {
+ "current_locations": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ }
+ }
+ },
+ "resource_name": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "response": {
+ "type": "flattened"
+ },
+ "service_name": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "status": {
+ "properties": {
+ "code": {
+ "type": "long"
+ },
+ "details": {
+ "type": "flattened"
+ },
+ "message": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ }
+ }
+ },
+ "type": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ }
+ }
+ },
+ "destination": {
+ "properties": {
+ "instance": {
+ "properties": {
+ "project_id": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "region": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "zone": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ }
+ }
+ },
+ "vpc": {
+ "properties": {
+ "project_id": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "subnetwork_name": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "vpc_name": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ }
+ }
+ }
+ }
+ },
+ "source": {
+ "properties": {
+ "instance": {
+ "properties": {
+ "project_id": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "region": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "zone": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ }
+ }
+ },
+ "vpc": {
+ "properties": {
+ "project_id": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "subnetwork_name": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "vpc_name": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "host": {
+ "properties": {
+ "containerized": {
+ "type": "boolean"
+ },
+ "os": {
+ "properties": {
+ "build": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "codename": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ }
+ }
+ }
+ }
+ },
+ "input": {
+ "properties": {
+ "type": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ }
+ }
+ },
+ "log": {
+ "properties": {
+ "offset": {
+ "type": "long"
+ }
+ }
+ }
+ }
+ },
+ "settings": {
+ "index": {
+ "codec": "best_compression",
+ "final_pipeline": ".fleet_final_pipeline-1",
+ "mapping": {
+ "ignore_malformed": "true",
+ "total_fields": {
+ "ignore_dynamic_beyond_limit": "true",
+ "limit": "1000"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/x-pack/test/cloud_security_posture_functional/es_archives/security_alerts/data.json.gz b/x-pack/test/cloud_security_posture_functional/es_archives/security_alerts/data.json.gz
new file mode 100644
index 0000000000000..93b2c20b81c86
Binary files /dev/null and b/x-pack/test/cloud_security_posture_functional/es_archives/security_alerts/data.json.gz differ
diff --git a/x-pack/test/cloud_security_posture_functional/es_archives/security_alerts/mappings.json b/x-pack/test/cloud_security_posture_functional/es_archives/security_alerts/mappings.json
new file mode 100644
index 0000000000000..d13b6edbd768f
--- /dev/null
+++ b/x-pack/test/cloud_security_posture_functional/es_archives/security_alerts/mappings.json
@@ -0,0 +1,8667 @@
+{
+ "type": "index",
+ "value": {
+ "aliases": {
+ ".alerts-security.alerts-default": {
+ "is_write_index": true
+ },
+ ".siem-signals-default": {
+ "is_write_index": false
+ }
+ },
+ "index": ".internal.alerts-security.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"
+ },
+ "asset": {
+ "properties": {
+ "criticality": {
+ "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"
+ },
+ "ancestors": {
+ "properties": {
+ "depth": {
+ "type": "long"
+ },
+ "id": {
+ "type": "keyword"
+ },
+ "index": {
+ "type": "keyword"
+ },
+ "rule": {
+ "type": "keyword"
+ },
+ "type": {
+ "type": "keyword"
+ }
+ }
+ },
+ "building_block_type": {
+ "type": "keyword"
+ },
+ "case_ids": {
+ "type": "keyword"
+ },
+ "consecutive_matches": {
+ "type": "long"
+ },
+ "depth": {
+ "type": "long"
+ },
+ "duration": {
+ "properties": {
+ "us": {
+ "type": "long"
+ }
+ }
+ },
+ "end": {
+ "type": "date"
+ },
+ "flapping": {
+ "type": "boolean"
+ },
+ "flapping_history": {
+ "type": "boolean"
+ },
+ "group": {
+ "properties": {
+ "id": {
+ "type": "keyword"
+ },
+ "index": {
+ "type": "integer"
+ }
+ }
+ },
+ "host": {
+ "properties": {
+ "criticality_level": {
+ "type": "keyword"
+ }
+ }
+ },
+ "instance": {
+ "properties": {
+ "id": {
+ "type": "keyword"
+ }
+ }
+ },
+ "intended_timestamp": {
+ "type": "date"
+ },
+ "last_detected": {
+ "type": "date"
+ },
+ "maintenance_window_ids": {
+ "type": "keyword"
+ },
+ "new_terms": {
+ "type": "keyword"
+ },
+ "original_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": {
+ "ignore_above": 1024,
+ "type": "keyword"
+ },
+ "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"
+ }
+ }
+ },
+ "original_time": {
+ "type": "date"
+ },
+ "previous_action_group": {
+ "type": "keyword"
+ },
+ "reason": {
+ "fields": {
+ "text": {
+ "type": "match_only_text"
+ }
+ },
+ "type": "keyword"
+ },
+ "risk_score": {
+ "type": "float"
+ },
+ "rule": {
+ "properties": {
+ "author": {
+ "type": "keyword"
+ },
+ "building_block_type": {
+ "type": "keyword"
+ },
+ "category": {
+ "type": "keyword"
+ },
+ "consumer": {
+ "type": "keyword"
+ },
+ "created_at": {
+ "type": "date"
+ },
+ "created_by": {
+ "type": "keyword"
+ },
+ "description": {
+ "type": "keyword"
+ },
+ "enabled": {
+ "type": "keyword"
+ },
+ "exceptions_list": {
+ "type": "object"
+ },
+ "execution": {
+ "properties": {
+ "timestamp": {
+ "type": "date"
+ },
+ "uuid": {
+ "type": "keyword"
+ }
+ }
+ },
+ "false_positives": {
+ "type": "keyword"
+ },
+ "from": {
+ "type": "keyword"
+ },
+ "immutable": {
+ "type": "keyword"
+ },
+ "interval": {
+ "type": "keyword"
+ },
+ "license": {
+ "type": "keyword"
+ },
+ "max_signals": {
+ "type": "long"
+ },
+ "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"
+ },
+ "threat": {
+ "properties": {
+ "framework": {
+ "type": "keyword"
+ },
+ "tactic": {
+ "properties": {
+ "id": {
+ "type": "keyword"
+ },
+ "name": {
+ "type": "keyword"
+ },
+ "reference": {
+ "type": "keyword"
+ }
+ }
+ },
+ "technique": {
+ "properties": {
+ "id": {
+ "type": "keyword"
+ },
+ "name": {
+ "type": "keyword"
+ },
+ "reference": {
+ "type": "keyword"
+ },
+ "subtechnique": {
+ "properties": {
+ "id": {
+ "type": "keyword"
+ },
+ "name": {
+ "type": "keyword"
+ },
+ "reference": {
+ "type": "keyword"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "timeline_id": {
+ "type": "keyword"
+ },
+ "timeline_title": {
+ "type": "keyword"
+ },
+ "timestamp_override": {
+ "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"
+ },
+ "threshold_result": {
+ "properties": {
+ "cardinality": {
+ "properties": {
+ "field": {
+ "type": "keyword"
+ },
+ "value": {
+ "type": "long"
+ }
+ }
+ },
+ "count": {
+ "type": "long"
+ },
+ "from": {
+ "type": "date"
+ },
+ "terms": {
+ "properties": {
+ "field": {
+ "type": "keyword"
+ },
+ "value": {
+ "type": "keyword"
+ }
+ }
+ }
+ }
+ },
+ "time_range": {
+ "format": "epoch_millis||strict_date_optional_time",
+ "type": "date_range"
+ },
+ "url": {
+ "ignore_above": 2048,
+ "index": false,
+ "type": "keyword"
+ },
+ "user": {
+ "properties": {
+ "criticality_level": {
+ "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"
+ }
+ }
+ },
+ "signal": {
+ "properties": {
+ "ancestors": {
+ "properties": {
+ "depth": {
+ "path": "kibana.alert.ancestors.depth",
+ "type": "alias"
+ },
+ "id": {
+ "path": "kibana.alert.ancestors.id",
+ "type": "alias"
+ },
+ "index": {
+ "path": "kibana.alert.ancestors.index",
+ "type": "alias"
+ },
+ "type": {
+ "path": "kibana.alert.ancestors.type",
+ "type": "alias"
+ }
+ }
+ },
+ "depth": {
+ "path": "kibana.alert.depth",
+ "type": "alias"
+ },
+ "group": {
+ "properties": {
+ "id": {
+ "path": "kibana.alert.group.id",
+ "type": "alias"
+ },
+ "index": {
+ "path": "kibana.alert.group.index",
+ "type": "alias"
+ }
+ }
+ },
+ "original_event": {
+ "properties": {
+ "action": {
+ "path": "kibana.alert.original_event.action",
+ "type": "alias"
+ },
+ "category": {
+ "path": "kibana.alert.original_event.category",
+ "type": "alias"
+ },
+ "code": {
+ "path": "kibana.alert.original_event.code",
+ "type": "alias"
+ },
+ "created": {
+ "path": "kibana.alert.original_event.created",
+ "type": "alias"
+ },
+ "dataset": {
+ "path": "kibana.alert.original_event.dataset",
+ "type": "alias"
+ },
+ "duration": {
+ "path": "kibana.alert.original_event.duration",
+ "type": "alias"
+ },
+ "end": {
+ "path": "kibana.alert.original_event.end",
+ "type": "alias"
+ },
+ "hash": {
+ "path": "kibana.alert.original_event.hash",
+ "type": "alias"
+ },
+ "id": {
+ "path": "kibana.alert.original_event.id",
+ "type": "alias"
+ },
+ "kind": {
+ "path": "kibana.alert.original_event.kind",
+ "type": "alias"
+ },
+ "module": {
+ "path": "kibana.alert.original_event.module",
+ "type": "alias"
+ },
+ "outcome": {
+ "path": "kibana.alert.original_event.outcome",
+ "type": "alias"
+ },
+ "provider": {
+ "path": "kibana.alert.original_event.provider",
+ "type": "alias"
+ },
+ "reason": {
+ "path": "kibana.alert.original_event.reason",
+ "type": "alias"
+ },
+ "risk_score": {
+ "path": "kibana.alert.original_event.risk_score",
+ "type": "alias"
+ },
+ "risk_score_norm": {
+ "path": "kibana.alert.original_event.risk_score_norm",
+ "type": "alias"
+ },
+ "sequence": {
+ "path": "kibana.alert.original_event.sequence",
+ "type": "alias"
+ },
+ "severity": {
+ "path": "kibana.alert.original_event.severity",
+ "type": "alias"
+ },
+ "start": {
+ "path": "kibana.alert.original_event.start",
+ "type": "alias"
+ },
+ "timezone": {
+ "path": "kibana.alert.original_event.timezone",
+ "type": "alias"
+ },
+ "type": {
+ "path": "kibana.alert.original_event.type",
+ "type": "alias"
+ }
+ }
+ },
+ "original_time": {
+ "path": "kibana.alert.original_time",
+ "type": "alias"
+ },
+ "reason": {
+ "path": "kibana.alert.reason",
+ "type": "alias"
+ },
+ "rule": {
+ "properties": {
+ "author": {
+ "path": "kibana.alert.rule.author",
+ "type": "alias"
+ },
+ "building_block_type": {
+ "path": "kibana.alert.building_block_type",
+ "type": "alias"
+ },
+ "created_at": {
+ "path": "kibana.alert.rule.created_at",
+ "type": "alias"
+ },
+ "created_by": {
+ "path": "kibana.alert.rule.created_by",
+ "type": "alias"
+ },
+ "description": {
+ "path": "kibana.alert.rule.description",
+ "type": "alias"
+ },
+ "enabled": {
+ "path": "kibana.alert.rule.enabled",
+ "type": "alias"
+ },
+ "false_positives": {
+ "path": "kibana.alert.rule.false_positives",
+ "type": "alias"
+ },
+ "from": {
+ "path": "kibana.alert.rule.from",
+ "type": "alias"
+ },
+ "id": {
+ "path": "kibana.alert.rule.uuid",
+ "type": "alias"
+ },
+ "immutable": {
+ "path": "kibana.alert.rule.immutable",
+ "type": "alias"
+ },
+ "interval": {
+ "path": "kibana.alert.rule.interval",
+ "type": "alias"
+ },
+ "license": {
+ "path": "kibana.alert.rule.license",
+ "type": "alias"
+ },
+ "max_signals": {
+ "path": "kibana.alert.rule.max_signals",
+ "type": "alias"
+ },
+ "name": {
+ "path": "kibana.alert.rule.name",
+ "type": "alias"
+ },
+ "note": {
+ "path": "kibana.alert.rule.note",
+ "type": "alias"
+ },
+ "references": {
+ "path": "kibana.alert.rule.references",
+ "type": "alias"
+ },
+ "risk_score": {
+ "path": "kibana.alert.risk_score",
+ "type": "alias"
+ },
+ "rule_id": {
+ "path": "kibana.alert.rule.rule_id",
+ "type": "alias"
+ },
+ "rule_name_override": {
+ "path": "kibana.alert.rule.rule_name_override",
+ "type": "alias"
+ },
+ "severity": {
+ "path": "kibana.alert.severity",
+ "type": "alias"
+ },
+ "tags": {
+ "path": "kibana.alert.rule.tags",
+ "type": "alias"
+ },
+ "threat": {
+ "properties": {
+ "framework": {
+ "path": "kibana.alert.rule.threat.framework",
+ "type": "alias"
+ },
+ "tactic": {
+ "properties": {
+ "id": {
+ "path": "kibana.alert.rule.threat.tactic.id",
+ "type": "alias"
+ },
+ "name": {
+ "path": "kibana.alert.rule.threat.tactic.name",
+ "type": "alias"
+ },
+ "reference": {
+ "path": "kibana.alert.rule.threat.tactic.reference",
+ "type": "alias"
+ }
+ }
+ },
+ "technique": {
+ "properties": {
+ "id": {
+ "path": "kibana.alert.rule.threat.technique.id",
+ "type": "alias"
+ },
+ "name": {
+ "path": "kibana.alert.rule.threat.technique.name",
+ "type": "alias"
+ },
+ "reference": {
+ "path": "kibana.alert.rule.threat.technique.reference",
+ "type": "alias"
+ },
+ "subtechnique": {
+ "properties": {
+ "id": {
+ "path": "kibana.alert.rule.threat.technique.subtechnique.id",
+ "type": "alias"
+ },
+ "name": {
+ "path": "kibana.alert.rule.threat.technique.subtechnique.name",
+ "type": "alias"
+ },
+ "reference": {
+ "path": "kibana.alert.rule.threat.technique.subtechnique.reference",
+ "type": "alias"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "timeline_id": {
+ "path": "kibana.alert.rule.timeline_id",
+ "type": "alias"
+ },
+ "timeline_title": {
+ "path": "kibana.alert.rule.timeline_title",
+ "type": "alias"
+ },
+ "timestamp_override": {
+ "path": "kibana.alert.rule.timestamp_override",
+ "type": "alias"
+ },
+ "to": {
+ "path": "kibana.alert.rule.to",
+ "type": "alias"
+ },
+ "type": {
+ "path": "kibana.alert.rule.type",
+ "type": "alias"
+ },
+ "updated_at": {
+ "path": "kibana.alert.rule.updated_at",
+ "type": "alias"
+ },
+ "updated_by": {
+ "path": "kibana.alert.rule.updated_by",
+ "type": "alias"
+ },
+ "version": {
+ "path": "kibana.alert.rule.version",
+ "type": "alias"
+ }
+ }
+ },
+ "status": {
+ "path": "kibana.alert.workflow_status",
+ "type": "alias"
+ },
+ "threshold_result": {
+ "properties": {
+ "cardinality": {
+ "properties": {
+ "field": {
+ "path": "kibana.alert.threshold_result.cardinality.field",
+ "type": "alias"
+ },
+ "value": {
+ "path": "kibana.alert.threshold_result.cardinality.value",
+ "type": "alias"
+ }
+ }
+ },
+ "count": {
+ "path": "kibana.alert.threshold_result.count",
+ "type": "alias"
+ },
+ "from": {
+ "path": "kibana.alert.threshold_result.from",
+ "type": "alias"
+ },
+ "terms": {
+ "properties": {
+ "field": {
+ "path": "kibana.alert.threshold_result.terms.field",
+ "type": "alias"
+ },
+ "value": {
+ "path": "kibana.alert.threshold_result.terms.value",
+ "type": "alias"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "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": {
+ "asset": {
+ "properties": {
+ "criticality": {
+ "type": "keyword"
+ }
+ }
+ },
+ "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-security.alerts-default"
+ },
+ "mapping": {
+ "ignore_malformed": "true",
+ "total_fields": {
+ "limit": "2500"
+ }
+ },
+ "number_of_replicas": "0",
+ "number_of_shards": "1"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/x-pack/test/cloud_security_posture_functional/page_objects/alerts_page.ts b/x-pack/test/cloud_security_posture_functional/page_objects/alerts_page.ts
new file mode 100644
index 0000000000000..f3a9f7b1448a8
--- /dev/null
+++ b/x-pack/test/cloud_security_posture_functional/page_objects/alerts_page.ts
@@ -0,0 +1,107 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import expect from '@kbn/expect';
+import { FtrService } from '../../functional/ftr_provider_context';
+
+const ALERT_TABLE_ROW_CSS_SELECTOR = '[data-test-subj="alertsTable"] .euiDataGridRow';
+const VISUALIZATIONS_SECTION_HEADER_TEST_ID = 'securitySolutionFlyoutVisualizationsHeader';
+const GRAPH_PREVIEW_TEST_ID = 'securitySolutionFlyoutGraphPreview';
+const GRAPH_PREVIEW_LOADING_TEST_ID = 'securitySolutionFlyoutGraphPreviewLoading';
+
+export class AlertsPageObject extends FtrService {
+ private readonly retry = this.ctx.getService('retry');
+ private readonly pageObjects = this.ctx.getPageObjects(['common', 'header']);
+ private readonly testSubjects = this.ctx.getService('testSubjects');
+ private readonly defaultTimeoutMs = this.ctx.getService('config').get('timeouts.waitFor');
+
+ async navigateToAlertsPage(urlQueryParams: string = ''): Promise {
+ await this.pageObjects.common.navigateToUrlWithBrowserHistory(
+ 'securitySolution',
+ '/alerts',
+ `${urlQueryParams && `?${urlQueryParams}`}`,
+ {
+ ensureCurrentUrl: false,
+ }
+ );
+ await this.pageObjects.header.waitUntilLoadingHasFinished();
+ }
+
+ getAbsoluteTimerangeFilter(from: string, to: string) {
+ return `timerange=(global:(linkTo:!(),timerange:(from:%27${from}%27,kind:absolute,to:%27${to}%27)))`;
+ }
+
+ getFlyoutFilter(alertId: string) {
+ return `flyout=(preview:!(),right:(id:document-details-right,params:(id:%27${alertId}%27,indexName:.internal.alerts-security.alerts-default-000001,scopeId:alerts-page)))`;
+ }
+
+ /**
+ * Clicks the refresh button on the Alerts page and waits for it to complete
+ */
+ async clickRefresh(): Promise {
+ await this.ensureOnAlertsPage();
+ await this.testSubjects.click('querySubmitButton');
+
+ // wait for refresh to complete
+ await this.retry.waitFor(
+ 'Alerts pages refresh button to be enabled',
+ async (): Promise => {
+ const refreshButton = await this.testSubjects.find('querySubmitButton');
+
+ return (await refreshButton.isDisplayed()) && (await refreshButton.isEnabled());
+ }
+ );
+ }
+
+ async ensureOnAlertsPage(): Promise {
+ await this.testSubjects.existOrFail('detectionsAlertsPage');
+ }
+
+ async waitForListToHaveAlerts(timeoutMs?: number): Promise {
+ const allEventRows = await this.testSubjects.findService.allByCssSelector(
+ ALERT_TABLE_ROW_CSS_SELECTOR
+ );
+
+ if (!Boolean(allEventRows.length)) {
+ await this.retry.waitForWithTimeout(
+ 'waiting for alerts to show up on alerts page',
+ timeoutMs ?? this.defaultTimeoutMs,
+ async (): Promise => {
+ await this.clickRefresh();
+
+ const allEventRowsInner = await this.testSubjects.findService.allByCssSelector(
+ ALERT_TABLE_ROW_CSS_SELECTOR
+ );
+
+ return Boolean(allEventRowsInner.length);
+ }
+ );
+ }
+ }
+
+ flyout = {
+ expandVisualizations: async (): Promise => {
+ await this.testSubjects.click(VISUALIZATIONS_SECTION_HEADER_TEST_ID);
+ },
+
+ assertGraphPreviewVisible: async () => {
+ return await this.testSubjects.existOrFail(GRAPH_PREVIEW_TEST_ID);
+ },
+
+ assertGraphNodesNumber: async (expected: number) => {
+ await this.flyout.waitGraphIsLoaded();
+ const graph = await this.testSubjects.find(GRAPH_PREVIEW_TEST_ID);
+ await graph.scrollIntoView();
+ const nodes = await graph.findAllByCssSelector('.react-flow__nodes .react-flow__node');
+ expect(nodes.length).to.be(expected);
+ },
+
+ waitGraphIsLoaded: async () => {
+ await this.testSubjects.missingOrFail(GRAPH_PREVIEW_LOADING_TEST_ID, { timeout: 10000 });
+ },
+ };
+}
diff --git a/x-pack/test/cloud_security_posture_functional/page_objects/index.ts b/x-pack/test/cloud_security_posture_functional/page_objects/index.ts
index 704f6310cdbb2..b7c20632e82f5 100644
--- a/x-pack/test/cloud_security_posture_functional/page_objects/index.ts
+++ b/x-pack/test/cloud_security_posture_functional/page_objects/index.ts
@@ -13,8 +13,10 @@ import { VulnerabilityDashboardPageProvider } from './vulnerability_dashboard_pa
import { BenchmarkPagePageProvider } from './benchmark_page';
import { CspSecurityCommonProvider } from './security_common';
import { RulePagePageProvider } from './rule_page';
+import { AlertsPageObject } from './alerts_page';
export const cloudSecurityPosturePageObjects = {
+ alerts: AlertsPageObject,
findings: FindingsPageProvider,
cloudPostureDashboard: CspDashboardPageProvider,
cisAddIntegration: AddCisIntegrationFormPageProvider,
diff --git a/x-pack/test/cloud_security_posture_functional/pages/alerts_flyout.ts b/x-pack/test/cloud_security_posture_functional/pages/alerts_flyout.ts
new file mode 100644
index 0000000000000..3095f6a663968
--- /dev/null
+++ b/x-pack/test/cloud_security_posture_functional/pages/alerts_flyout.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 { waitForPluginInitialized } from '../../cloud_security_posture_api/utils';
+import type { FtrProviderContext } from '../ftr_provider_context';
+
+// eslint-disable-next-line import/no-default-export
+export default function ({ getPageObjects, getService }: FtrProviderContext) {
+ const retry = getService('retry');
+ const logger = getService('log');
+ const supertest = getService('supertest');
+ const esArchiver = getService('esArchiver');
+ const pageObjects = getPageObjects(['common', 'header', 'alerts']);
+ const alertsPage = pageObjects.alerts;
+
+ describe('Security Alerts Page - Graph visualization', function () {
+ this.tags(['cloud_security_posture_graph_viz']);
+
+ before(async () => {
+ await esArchiver.load(
+ 'x-pack/test/cloud_security_posture_functional/es_archives/security_alerts'
+ );
+ await esArchiver.load(
+ 'x-pack/test/cloud_security_posture_functional/es_archives/logs_gcp_audit'
+ );
+
+ await waitForPluginInitialized({ retry, supertest, logger });
+
+ // Setting the timerange to fit the data and open the flyout for a specific alert
+ await alertsPage.navigateToAlertsPage(
+ `${alertsPage.getAbsoluteTimerangeFilter(
+ '2024-10-13T00:00:00.000Z',
+ '2024-10-14T00:00:00.000Z'
+ )}&${alertsPage.getFlyoutFilter(
+ '589e086d7ceec7d4b353340578bd607e96fbac7eab9e2926f110990be15122f1'
+ )}`
+ );
+
+ await alertsPage.waitForListToHaveAlerts();
+
+ await alertsPage.flyout.expandVisualizations();
+ });
+
+ after(async () => {
+ await esArchiver.unload(
+ 'x-pack/test/cloud_security_posture_functional/es_archives/security_alerts'
+ );
+ await esArchiver.unload(
+ 'x-pack/test/cloud_security_posture_functional/es_archives/logs_gcp_audit'
+ );
+ });
+
+ it('should render graph visualization', async () => {
+ await alertsPage.flyout.assertGraphPreviewVisible();
+ await alertsPage.flyout.assertGraphNodesNumber(3);
+ });
+ });
+}
diff --git a/x-pack/test/cloud_security_posture_functional/pages/index.ts b/x-pack/test/cloud_security_posture_functional/pages/index.ts
index 1edf38dc41ec9..0114b6a8ce4dc 100644
--- a/x-pack/test/cloud_security_posture_functional/pages/index.ts
+++ b/x-pack/test/cloud_security_posture_functional/pages/index.ts
@@ -36,5 +36,6 @@ export default function ({ getPageObjects, loadTestFile }: FtrProviderContext) {
loadTestFile(require.resolve('./vulnerabilities'));
loadTestFile(require.resolve('./vulnerabilities_grouping'));
loadTestFile(require.resolve('./benchmark'));
+ loadTestFile(require.resolve('./alerts_flyout'));
});
}
diff --git a/x-pack/test/functional/apps/infra/node_details.ts b/x-pack/test/functional/apps/infra/node_details.ts
index afacc8d63c3e3..0f1de8cb9c8bf 100644
--- a/x-pack/test/functional/apps/infra/node_details.ts
+++ b/x-pack/test/functional/apps/infra/node_details.ts
@@ -404,8 +404,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
await pageObjects.assetDetails.clickProcessesTab();
const processesTotalValue =
await pageObjects.assetDetails.getProcessesTabContentTotalValue();
- const processValue = await processesTotalValue.getVisibleText();
- expect(processValue).to.eql('N/A');
+ await retry.tryForTime(5000, async () => {
+ expect(await processesTotalValue.getVisibleText()).to.eql('N/A');
+ });
});
});
});
@@ -510,8 +511,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
it('should render processes tab and with Total Value summary', async () => {
const processesTotalValue =
await pageObjects.assetDetails.getProcessesTabContentTotalValue();
- const processValue = await processesTotalValue.getVisibleText();
- expect(processValue).to.eql('313');
+ await retry.tryForTime(5000, async () => {
+ expect(await processesTotalValue.getVisibleText()).to.eql('313');
+ });
});
it('should expand processes table row', async () => {
diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/sourcerer/create_runtime_field.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/sourcerer/create_runtime_field.cy.ts
index a96762e530bdb..b8a7bed3c22b9 100644
--- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/sourcerer/create_runtime_field.cy.ts
+++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/sourcerer/create_runtime_field.cy.ts
@@ -8,7 +8,10 @@
import { login } from '../../../tasks/login';
import { visitWithTimeRange } from '../../../tasks/navigation';
import { openTimelineUsingToggle } from '../../../tasks/security_main';
-import { openTimelineFieldsBrowser, populateTimeline } from '../../../tasks/timeline';
+import {
+ createRuntimeFieldFromTimelne as createRuntimeFieldFromTimeline,
+ populateTimeline,
+} from '../../../tasks/timeline';
import { hostsUrl, ALERTS_URL } from '../../../urls/navigation';
@@ -20,14 +23,13 @@ import { waitForAlertsToPopulate } from '../../../tasks/create_new_rule';
import { createField } from '../../../tasks/create_runtime_field';
import { openAlertsFieldBrowser } from '../../../tasks/alerts';
import { GET_DATA_GRID_HEADER } from '../../../screens/common/data_grid';
-import { GET_TIMELINE_HEADER } from '../../../screens/timeline';
import { deleteRuntimeField } from '../../../tasks/api_calls/sourcerer';
+import { SAVE_FIELD_BUTTON } from '../../../screens/create_runtime_field';
const alertRunTimeField = 'field.name.alert.page';
const timelineRuntimeField = 'field.name.timeline';
-// FLAKY: https://github.com/elastic/kibana/issues/183104
-describe.skip('Create DataView runtime field', { tags: ['@ess', '@serverless'] }, () => {
+describe('Create DataView runtime field', { tags: ['@ess', '@serverless'] }, () => {
beforeEach(() => {
login();
deleteRuntimeField('security-solution-default', alertRunTimeField);
@@ -48,9 +50,9 @@ describe.skip('Create DataView runtime field', { tags: ['@ess', '@serverless'] }
visitWithTimeRange(hostsUrl('allHosts'));
openTimelineUsingToggle();
populateTimeline();
- openTimelineFieldsBrowser();
-
- createField(timelineRuntimeField);
- cy.get(GET_TIMELINE_HEADER(timelineRuntimeField)).should('exist');
+ createRuntimeFieldFromTimeline(timelineRuntimeField);
+ // NOTE: the field creation dialog should be closed now
+ // meaning that the field creation has been successful
+ cy.get(SAVE_FIELD_BUTTON).should('not.exist');
});
});
diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/sourcerer/sourcerer_timeline.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/sourcerer/sourcerer_timeline.cy.ts
index bb4010a6db4f6..9d2e1ac2e11a5 100644
--- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/sourcerer/sourcerer_timeline.cy.ts
+++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/sourcerer/sourcerer_timeline.cy.ts
@@ -62,8 +62,7 @@ describe('Timeline scope', { tags: ['@ess', '@serverless', '@skipInServerless']
isNotSourcererOption(`${DEFAULT_ALERTS_INDEX}-default`);
});
- // FLAKY: https://github.com/elastic/kibana/issues/173854
- describe.skip('Modified badge', () => {
+ describe('Modified badge', () => {
it('Selecting new data view does not add a modified badge', () => {
openTimelineUsingToggle();
cy.get(SOURCERER.badgeModified).should(`not.exist`);
diff --git a/x-pack/test/security_solution_cypress/cypress/screens/timeline.ts b/x-pack/test/security_solution_cypress/cypress/screens/timeline.ts
index 66fe11bb2dfd3..a4aac97091af2 100644
--- a/x-pack/test/security_solution_cypress/cypress/screens/timeline.ts
+++ b/x-pack/test/security_solution_cypress/cypress/screens/timeline.ts
@@ -166,6 +166,9 @@ export const TIMELINE_EVENTS_COUNT_PREV_PAGE =
export const TIMELINE_FIELDS_BUTTON =
'[data-test-subj="timeline"] [data-test-subj="show-field-browser"]';
+export const TIMELINE_DISCOVER_FIELDS_BUTTON =
+ '[data-test-subj="timeline"] [data-test-subj="dataView-add-field_btn"]';
+
export const TIMELINE_FILTER = (filter: TimelineFilter) =>
`[data-test-subj~="filter"][data-test-subj~="filter-enabled"][data-test-subj~="filter-key-${
filter.field
@@ -307,10 +310,6 @@ export const HOVER_ACTIONS = {
export const TIMELINE_FILTER_BADGE_ENABLED = '[data-test-subj~="filter-enabled"]';
-export const GET_TIMELINE_HEADER = (fieldName: string) => {
- return `[data-test-subj="timeline"] [data-test-subj="header-text-${fieldName}"]`;
-};
-
export const ESQL_TAB = getDataTestSubjectSelector('timelineTabs-esql');
export const TIMELINE_DATE_PICKER_CONTAINER = getDataTestSubjectSelector(
diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/timeline.ts b/x-pack/test/security_solution_cypress/cypress/tasks/timeline.ts
index 6c9f7f50d259c..5866011ec1cbf 100644
--- a/x-pack/test/security_solution_cypress/cypress/tasks/timeline.ts
+++ b/x-pack/test/security_solution_cypress/cypress/tasks/timeline.ts
@@ -90,6 +90,7 @@ import {
TIMELINE_FULL_SCREEN_BUTTON,
QUERY_EVENT_COUNT,
TIMELINE_ENABLE_DISABLE_ALL_ROW_RENDERER,
+ TIMELINE_DISCOVER_FIELDS_BUTTON,
} from '../screens/timeline';
import { REFRESH_BUTTON, TIMELINE, TIMELINES_TAB_TEMPLATE } from '../screens/timelines';
@@ -99,6 +100,7 @@ import { closeFieldsBrowser, filterFieldsBrowser } from './fields_browser';
import { TIMELINE_CONTEXT_MENU_BTN } from '../screens/alerts';
import { LOADING_INDICATOR } from '../screens/security_header';
import { TOASTER } from '../screens/alerts_detection_rules';
+import { RUNTIME_FIELD_INPUT, SAVE_FIELD_BUTTON } from '../screens/create_runtime_field';
const hostExistsQuery = 'host.name: *';
@@ -380,6 +382,18 @@ export const openTimelineFieldsBrowser = () => {
cy.get(TIMELINE_FIELDS_BUTTON).first().click();
};
+export const openTimelineDiscoverAddField = () => {
+ cy.get(TIMELINE_DISCOVER_FIELDS_BUTTON).first().click();
+};
+
+export const createRuntimeFieldFromTimelne = (
+ fieldName: string
+): Cypress.Chainable> => {
+ openTimelineDiscoverAddField();
+ cy.get(RUNTIME_FIELD_INPUT).type(fieldName);
+ return cy.get(SAVE_FIELD_BUTTON).click();
+};
+
export const openTimelineInspectButton = () => {
cy.get(TIMELINE_INSPECT_BUTTON).should('not.be.disabled');
cy.get(TIMELINE_INSPECT_BUTTON).click();