Skip to content

Commit 0cf932b

Browse files
maxcoldstephmilovicalexreal1314
authored andcommitted
Ask AI Assistant in generic entity flyout (#234324)
## Summary This PR adds basic "Ask AI Assistant" functionality to the Generic Entity flyout in Asset Inventory. The Asset Inventory is still in Tech Preview and behind a feature flag, so this functionality when merged will have the same availability. The implementation follows the approach of the same functionality available for Alerts The feature will be under Technical Preview as Asset Inventory itself is under Technical preview and behind an Advanced Setting Contributes to: - elastic/security-team#13836 ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [x] This was checked for breaking HTTP API changes, and any breaking changes have been approved by the breaking-change committee. The `release_note:breaking` label should be applied in these situations. - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [x] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) - [x] Review the [backport guidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing) and apply applicable `backport:*` labels. ### How to test 0. set up AI Assistant LLM Connectors, eg via `kibana.dev.yml` flag `xpack.actions.preconfigured`. You will need LLM credentials for that. Reach out to @maxcold if you don't have it. make sure to run elasticsearch cluster without the flag `xpack.ml.enabled=false` 1. Install Cloud Asset Discovery integration https://localhost:5601/app/integrations/detail/cloud_asset_inventory 2. Reindex Asset Inventory, you will need credentials from an env with asset inventory data, reach out to @maxcold if you don't have it: ``` POST _reindex?wait_for_completion=true { "conflicts": "proceed", "source": { "remote": { "host": "${ES_REMOTE_HOST}", "username": "${ES_REMOTE_USER}", "password": "${ES_REMOTE_PASS}" }, "index": "logs-cloud_asset_inventory*", "query": { "bool": { "must": [ { "range": { "@timestamp": { "gte": "now-1d" } } } ] } } }, "dest": { "op_type": "create", "index": "logs-cloud_asset_inventory.asset_inventory-default" } } ``` 3. Enable Asset Inventory on Kibana Settings 4. Enable Asset Inventory on Security -> Inventory page. ### Screenshots <img width="1728" height="873" alt="Screenshot 2025-09-12 at 13 25 38" src="https://github.com/user-attachments/assets/9abf8597-b404-467a-a4fe-24b4df5fa722" /> <img width="1728" height="875" alt="Screenshot 2025-09-12 at 13 25 46" src="https://github.com/user-attachments/assets/e43e0f87-ff13-4b8e-b6e5-5da3dd4e9a86" /> Preview mode - hide 'Ask AI Assistant' button - aligned with alert flyout in preview mode: <img width="1477" height="932" alt="image" src="https://github.com/user-attachments/assets/c9f2eeb0-3d60-49e9-8a7b-671cb57a1431" /> <img width="1727" height="871" alt="Screenshot 2025-09-12 at 13 26 23" src="https://github.com/user-attachments/assets/41cb16d7-6d25-4601-b5c1-3a28c31e9be2" /> --------- Co-authored-by: Steph Milovic <[email protected]> Co-authored-by: alex prozorov <[email protected]>
1 parent da33077 commit 0cf932b

File tree

14 files changed

+482
-6
lines changed

14 files changed

+482
-6
lines changed

x-pack/solutions/security/plugins/elastic_assistant/common/anonymization/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,18 @@ export const DEFAULT_ALLOW = [
1414
'actions.status',
1515
'actions.context',
1616
'agent.id',
17+
'cloud.account.name',
1718
'cloud.availability_zone',
1819
'cloud.provider',
1920
'cloud.region',
21+
'cloud.service.name',
2022
'destination.ip',
2123
'dns.question.name',
2224
'dns.question.type',
25+
'entity.id',
26+
'entity.name',
27+
'entity.sub_type',
28+
'entity.type',
2329
'event.category',
2430
'event.dataset',
2531
'event.module',
@@ -30,12 +36,14 @@ export const DEFAULT_ALLOW = [
3036
'file.path',
3137
'group.id',
3238
'group.name',
39+
'host.architecture',
3340
'host.asset.criticality',
3441
'host.name',
3542
'host.os.name',
3643
'host.os.version',
3744
'host.risk.calculated_level',
3845
'host.risk.calculated_score_norm',
46+
'host.type',
3947
'kibana.alert.original_time',
4048
'kibana.alert.risk_score',
4149
'kibana.alert.rule.description',
@@ -117,6 +125,8 @@ export const DEFAULT_ALLOW = [
117125

118126
/** By default, these fields will be anonymized */
119127
export const DEFAULT_ALLOW_REPLACEMENT = [
128+
'cloud.account.name',
129+
'entity.name',
120130
'host.ip', // not a default allow field, but anonymized by default
121131
'host.name',
122132
'user.name',

x-pack/solutions/security/plugins/elastic_assistant/server/lib/prompt/local_prompt_object.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
RULE_ANALYSIS,
3030
DATA_QUALITY_ANALYSIS,
3131
ALERT_EVALUATION,
32+
ENTITY_ANALYSIS,
3233
starterPromptTitle1,
3334
starterPromptDescription1,
3435
starterPromptIcon1,
@@ -101,6 +102,7 @@ export const promptDictionary = {
101102
'defendInsights-policyResponseFailureRemediationLink',
102103
// context prompts
103104
alertEvaluation: `alertEvaluation`,
105+
assetAnalysis: `assetAnalysis`,
104106
dataQualityAnalysis: 'dataQualityAnalysis',
105107
ruleAnalysis: 'ruleAnalysis',
106108
// starter prompts
@@ -416,6 +418,13 @@ export const localPrompts: Prompt[] = [
416418
default: ALERT_EVALUATION,
417419
},
418420
},
421+
{
422+
promptId: promptDictionary.assetAnalysis,
423+
promptGroupId: promptGroupId.aiAssistant,
424+
prompt: {
425+
default: ENTITY_ANALYSIS,
426+
},
427+
},
419428
{
420429
promptId: promptDictionary.dataQualityAnalysis,
421430
promptGroupId: promptGroupId.aiAssistant,

x-pack/solutions/security/plugins/elastic_assistant/server/lib/prompt/prompts.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,24 @@ Formatting Requirements:
219219
- Include relevant emojis in section headers for visual clarity (e.g., 📝, 🛡️, 🔍, 📚).
220220
`;
221221

222+
export const ENTITY_ANALYSIS = `Your primary function is to analyze asset and entity data to provide security insights. You will be provided with a JSON object containing the context of a specific asset (e.g., a host, user, service or cloud resource). Your response must be structured, contextual, and directly address the user's query if one is provided. If no specific query is given, provide a general analysis based on the structure below.
223+
Your response must be in markdown format and include the following sections:
224+
**1. 🔍 Asset Overview**
225+
- Begin by acknowledging the asset you are analyzing using its primary identifiers (e.g., "Analyzing host \`[host.name]\` with IP \`[host.ip]\`").
226+
- Provide a concise summary of the asset's most critical attributes from the provided context.
227+
- Describe its key relationships and dependencies (e.g., "This asset is part of the \`[cloud.project.name]\` project and is located in the \`[cloud.availability_zone]\` zone.").
228+
**2. 💡 Investigation & Analytics**
229+
- Based on the asset's type and attributes, suggest potential investigation paths or common attack vectors.
230+
- **Generate contextual ES|QL queries** to help the user investigate further. Format all queries as code blocks. Your generated queries should address common analytical questions, such as:
231+
- Finding related security events (e.g., login attempts, network traffic, process executions).
232+
- Identifying other assets with similar attributes.
233+
- Searching for Indicators of Compromise (IoCs) relevant to the asset type.
234+
- If the user asks a question that can be answered with a query, provide the query as the primary answer.
235+
**General Instructions:**
236+
- **Context Awareness:** Your entire analysis must be derived from the provided asset context. If a piece of information is not available in the context (or appears to be anonymized), state that and proceed with the available data.
237+
- **Query Generation:** When asked to "write a query" or a similar request, your primary output for that section should be a valid, ready-to-use ES|QL query based on the entity's schema.
238+
- **Formatting:** Use markdown headers, tables, code blocks, and bullet points to ensure the output is clear, organized, and easily readable. Use concise, actionable language.`;
239+
222240
export const starterPromptTitle1 = 'Alerts';
223241
export const starterPromptDescription1 = 'Most important alerts from the last 24 hrs';
224242
export const starterPromptIcon1 = 'bell';

x-pack/solutions/security/plugins/security_solution/public/assistant/content/prompt_contexts/index.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ import * as i18nDataQuality from '@kbn/ecs-data-quality-dashboard';
1010
import * as i18n from './translations';
1111
import * as i18nDetections from '../../../detection_engine/common/translations';
1212
import * as i18nEventDetails from '../../../common/components/event_details/translations';
13+
import * as i18nEntityDetails from '../../../flyout/entity_details/shared/translations';
1314

1415
export const PROMPT_CONTEXT_ALERT_CATEGORY = 'alert';
1516
export const PROMPT_CONTEXT_EVENT_CATEGORY = 'event';
1617
export const PROMPT_CONTEXT_DETECTION_RULES_CATEGORY = 'detection-rules';
1718
export const DATA_QUALITY_DASHBOARD_CATEGORY = 'data-quality-dashboard';
19+
export const PROMPT_CONTEXT_ASSET_CATEGORY = 'asset';
1820

1921
/**
2022
* Global list of PromptContexts intended to be used throughout Security Solution.
@@ -61,4 +63,13 @@ export const getPromptContexts = (
6163
description: i18nDetections.RULE_MANAGEMENT_CONTEXT_DESCRIPTION,
6264
tooltip: i18nDetections.RULE_MANAGEMENT_CONTEXT_TOOLTIP,
6365
},
66+
/**
67+
* Entity context, made available on the Asset Inventory page in the entity details flyout
68+
*/
69+
[PROMPT_CONTEXT_ASSET_CATEGORY]: {
70+
category: PROMPT_CONTEXT_ASSET_CATEGORY,
71+
suggestedUserPrompt: prompts[PROMPT_CONTEXT_ASSET_CATEGORY],
72+
description: i18nEntityDetails.ENTITY_CONTEXT_DESCRIPTION,
73+
tooltip: i18nEntityDetails.ENTITY_CONTEXT_TOOLTIP,
74+
},
6475
});

x-pack/solutions/security/plugins/security_solution/public/assistant/content/prompt_contexts/use_find_prompt_contexts.test.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { useFindPrompts } from '@kbn/elastic-assistant';
1212
import { DATA_QUALITY_SUGGESTED_USER_PROMPT } from '@kbn/ecs-data-quality-dashboard';
1313
import { EXPLAIN_THEN_SUMMARIZE_RULE_DETAILS } from '../../../detection_engine/common/translations';
1414
import { EXPLAIN_THEN_SUMMARIZE_SUGGEST_INVESTIGATION_GUIDE } from '../prompts/user/translations';
15+
import { ASSET_INVENTORY_ENTITY_PROMPT } from '../../../flyout/entity_details/shared/translations';
1516

1617
const mockPrompts = [
1718
{
@@ -26,6 +27,10 @@ const mockPrompts = [
2627
promptId: 'ruleAnalysis',
2728
prompt: 'RULE ANALYSIS',
2829
},
30+
{
31+
promptId: 'assetAnalysis',
32+
prompt: 'ASSET ANALYSIS',
33+
},
2934
];
3035
jest.mock('@kbn/elastic-assistant');
3136

@@ -47,6 +52,12 @@ describe('useFindPromptContexts', () => {
4752
suggestedUserPrompt: 'ALERT EVALUATION',
4853
tooltip: 'Add this alert as context',
4954
},
55+
asset: {
56+
category: 'asset',
57+
description: 'Entity details',
58+
suggestedUserPrompt: 'ASSET ANALYSIS',
59+
tooltip: 'Asset details from inventory',
60+
},
5061
'data-quality-dashboard': {
5162
category: 'data-quality-dashboard',
5263
description: 'Data Quality (index)',
@@ -83,6 +94,12 @@ describe('useFindPromptContexts', () => {
8394
suggestedUserPrompt: EXPLAIN_THEN_SUMMARIZE_SUGGEST_INVESTIGATION_GUIDE,
8495
tooltip: 'Add this alert as context',
8596
},
97+
asset: {
98+
category: 'asset',
99+
description: 'Entity details',
100+
suggestedUserPrompt: ASSET_INVENTORY_ENTITY_PROMPT,
101+
tooltip: 'Asset details from inventory',
102+
},
86103
'data-quality-dashboard': {
87104
category: 'data-quality-dashboard',
88105
description: 'Data Quality (index)',

x-pack/solutions/security/plugins/security_solution/public/assistant/content/prompt_contexts/use_find_prompt_contexts.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ import type { FindSecurityAIPromptsRequestQuery } from '@kbn/elastic-assistant-c
1212
import { DATA_QUALITY_SUGGESTED_USER_PROMPT } from '@kbn/ecs-data-quality-dashboard';
1313
import { EXPLAIN_THEN_SUMMARIZE_RULE_DETAILS } from '../../../detection_engine/common/translations';
1414
import { EXPLAIN_THEN_SUMMARIZE_SUGGEST_INVESTIGATION_GUIDE } from '../prompts/user/translations';
15+
import { ASSET_INVENTORY_ENTITY_PROMPT } from '../../../flyout/entity_details/shared/translations';
1516
import {
1617
DATA_QUALITY_DASHBOARD_CATEGORY,
1718
getPromptContexts,
1819
PROMPT_CONTEXT_ALERT_CATEGORY,
1920
PROMPT_CONTEXT_DETECTION_RULES_CATEGORY,
2021
PROMPT_CONTEXT_EVENT_CATEGORY,
22+
PROMPT_CONTEXT_ASSET_CATEGORY,
2123
} from '.';
2224
export interface UseFindPromptContextsParams {
2325
context: {
@@ -47,6 +49,9 @@ export const useFindPromptContexts = (payload: UseFindPromptContextsParams) => {
4749
[PROMPT_CONTEXT_DETECTION_RULES_CATEGORY]:
4850
prompts.find(({ promptId }) => promptId === 'ruleAnalysis')?.prompt ??
4951
EXPLAIN_THEN_SUMMARIZE_RULE_DETAILS,
52+
[PROMPT_CONTEXT_ASSET_CATEGORY]:
53+
prompts.find(({ promptId }) => promptId === 'assetAnalysis')?.prompt ??
54+
ASSET_INVENTORY_ENTITY_PROMPT,
5055
});
5156
return PROMPT_CONTEXTS;
5257
};

x-pack/solutions/security/plugins/security_solution/public/assistant/provider.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export const AssistantProvider: FC<PropsWithChildren<unknown>> = ({ children })
4242
},
4343
params: {
4444
prompt_group_id: 'aiAssistant',
45-
prompt_ids: ['alertEvaluation', 'dataQualityAnalysis', 'ruleAnalysis'],
45+
prompt_ids: ['alertEvaluation', 'dataQualityAnalysis', 'ruleAnalysis', 'assetAnalysis'],
4646
},
4747
});
4848
const promptContext = useObservable(

x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/generic_right/footer.tsx

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { EuiFlyoutFooter, EuiPanel, EuiFlexGroup, EuiFlexItem, EuiLink } from '@
1010
import type { EntityEcs } from '@kbn/securitysolution-ecs/src/entity';
1111
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
1212
import { i18n } from '@kbn/i18n';
13+
import { NewChatByTitle } from '@kbn/elastic-assistant';
1314
import { DocumentEventTypes } from '../../../common/lib/telemetry';
1415
import { TakeAction } from '../shared/components/take_action';
1516
import {
@@ -19,19 +20,31 @@ import {
1920
import { GenericEntityPanelKey } from '../shared/constants';
2021
import { GENERIC_ENTITY_PREVIEW_BANNER } from '../../document_details/preview/constants';
2122
import { useKibana } from '../../../common/lib/kibana';
23+
import { ASK_AI_ASSISTANT } from '../shared/translations';
24+
import { useAssetInventoryAssistant } from './hooks/use_asset_inventory_assistant';
25+
26+
interface GenericEntityFlyoutFooterProps {
27+
entityId: EntityEcs['id'];
28+
isPreviewMode: boolean;
29+
scopeId: string;
30+
entityFields: Record<string, string[]>;
31+
}
2232

2333
export const GenericEntityFlyoutFooter = ({
2434
entityId,
2535
isPreviewMode,
2636
scopeId,
27-
}: {
28-
entityId: EntityEcs['id'];
29-
isPreviewMode: boolean;
30-
scopeId: string;
31-
}) => {
37+
entityFields,
38+
}: GenericEntityFlyoutFooterProps) => {
3239
const { openFlyout } = useExpandableFlyoutApi();
3340
const { telemetry } = useKibana().services;
3441

42+
const { showAssistant, showAssistantOverlay } = useAssetInventoryAssistant({
43+
entityId,
44+
entityFields,
45+
isPreviewMode,
46+
});
47+
3548
const openDocumentFlyout = useCallback(() => {
3649
openFlyout({
3750
right: {
@@ -70,6 +83,11 @@ export const GenericEntityFlyoutFooter = ({
7083
<EuiFlexGroup justifyContent="flexEnd" alignItems="center">
7184
{isPreviewMode && <EuiFlexItem grow={false}>{fullDetailsLink}</EuiFlexItem>}
7285

86+
{showAssistant && (
87+
<EuiFlexItem grow={false}>
88+
<NewChatByTitle showAssistantOverlay={showAssistantOverlay} text={ASK_AI_ASSISTANT} />
89+
</EuiFlexItem>
90+
)}
7391
<EuiFlexItem grow={false}>
7492
<TakeAction
7593
isDisabled={!entityId}

0 commit comments

Comments
 (0)