Skip to content

[AZ] Forensic Worker with actions - #290164

Draft
ymao1 wants to merge 40 commits into
elastic:mainfrom
ymao1:az-forensic-worker-manual
Draft

ymao1 wants to merge 40 commits into
elastic:mainfrom
ymao1:az-forensic-worker-manual

Conversation

@ymao1

@ymao1 ymao1 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Note

Keeping this as draft for prototyping and will lift pieces to production-ize as they are approved

Lifts the Forensic Worker demonstrated via a POC branched off of #287301 into an AZ worker based on the latest in main.

  • Worker is manually triggered. This workflow assumes that an investigation conversation has already been created by another worker prior to hand-off/user-approval gate so it requires attack_discovery_alert_id and investigation_id as inputs.
  • Worker loads the alerts related to this attack discovery alert and gets the top affected host (using an aggregation). If no hosts are present in the linked alerts, the skill is not triggered. Question do we want to run the forensic analysis on more than one host?
  • Added 3 AlertZero proposal actions that map to the Endpoint response actions isolate-host, kill-process and suspend-process. These actions are run via a custom workflow step and triggered with an AlertZero action workflow following the model in [AlertZero] Action proposals common layer #289683.
  • Adds 2 attachment types: security.investigation.timeline and security.investigation.iocs. When the skill reconstructs the incident timeline and extracts IoCs, they are returned as part of the structured output and added to the investigation as an attachment. Added basic inline rendering for this - needs UX review.
  • TODO - when action fails, update the investigation conversation. Is it possible to pass the investigation ID through to the proposal?

Run with the following feature flags:

uiSettings.overrides:
  securitySolution:enableAttackDiscoveryWorkflows: true
  workflows:ui:showManagedWorkflows: true
  workflows:experimentalFeatures: true
  agentBuilder:experimentalFeatures: true

xpack.alertzero.enabled: true
xpack.agenticInvestigations.enabled: true
xpack.securitySolution.enableExperimental:
  - endpointForensicAnalysisSkill
feature_flags.overrides:
  securitySolution.attackDiscoveryWorkflowsEnabled: true

Use the following workflow to trigger this worker workflow. This mimics a flow the Attack Discovery Worker might take when an attack is generated. Worker creates a conversation using an investigation template, then "checks whether true positive" (always passes). Once Worker has determined an attack is a true positive, calls the Forensic Worker to reconstruct incident timeline and recommend actions. Proposal steps at end are modeled after #289683 and can be fully tested once that PR is merged.

name: Not Attack Discovery Worker
description: >
  For testing Forensic Worker. Triggered manually with
  attack discovery alert ID. Workflow picks up where the
  real Attack Discovery worker would determine attack to
  be true positive.
enabled: true
triggers:
  - type: manual
    inputs:
      properties:
        attack_discovery_alert_id:
          type: string
          description: The ID of the attack discovery alert to be analyzed

steps:
  - name: fetch_attack_discovery_alert
    type: elasticsearch.search
    on-failure:
      continue: true
    with:
      index: ".alerts-security.attack.discovery.alerts-{{ workflow.spaceId }}*,.adhoc.alerts-security.attack.discovery.alerts-{{ workflow.spaceId }}*"
      ignore_unavailable: true
      size: 1
      _source:
        - kibana.alert.uuid
        - kibana.alert.attack_discovery.title
        - kibana.alert.attack_discovery.details_markdown
      query:
        bool:
          should:
            - ids:
                values:
                  - "{{ inputs.attack_discovery_alert_id }}"
            - term:
                kibana.alert.uuid: "{{ inputs.attack_discovery_alert_id }}"
          minimum_should_match: 1

  - name: open_investigation
    type: ai.conversation.create
    if: "${{ steps.fetch_attack_discovery_alert.output.hits.hits[0]._source['kibana.alert.uuid'] != blank }}"
    with:
      title: "{{ steps.fetch_attack_discovery_alert.output.hits.hits[0]._source['kibana.alert.attack_discovery.title'] }}"
      access_control:
        access_mode: public
      template_id: investigation
      metadata:
        status: open
        description: "{{ steps.fetch_attack_discovery_alert.output.hits.hits[0]._source['kibana.alert.attack_discovery.title'] }}"
        summary: "{{ steps.fetch_attack_discovery_alert.output.hits.hits[0]._source['kibana.alert.attack_discovery.details_markdown'] }}"
        workflow_execution_id: "{{ execution.id }}"
    on-failure:
      continue: true

  - name: assert_true_positive
    type: ai.conversation.metadata.patch
    with:
      conversation_id: "{{ steps.open_investigation.output.id }}"
      updates:
        verdict: "true_positive"

  - name: forensic_analysis_and_recommend_action
    type: workflow.execute
    with:
      workflow-id: endpoint-forensic-analysis
      inputs:
        attack_discovery_alert_id: "{{ steps.fetch_attack_discovery_alert.output.hits.hits[0]._source['kibana.alert.uuid'] }}"
        investigation_id: "{{ steps.open_investigation.output.id }}"

  - name: propose_actions
    type: foreach
    if: "${{ steps.forensic_analysis_and_recommend_action.error == null and steps.forensic_analysis_and_recommend_action.output.propose == true }}"
    foreach: "${{ steps.forensic_analysis_and_recommend_action.output.recommendedActions | default: [] }}"
    steps:
      - name: propose_action
        type: workflow.executeAsync
        with:
          # from https://github.com/elastic/kibana/pull/289683
          workflow-id: system-create-investigation-proposal
          inputs:
            conversationId: "{{ steps.open_investigation.output.conversation_id }}"
            comment: "{{ foreach.item.comment }}"
            actionWorkflowId: "{{ foreach.item.actionId }}"
            actionInput: '${{ foreach.item.actionInput }}'
    on-failure:
      continue: true

Related PRs

@infra-vault-gh-plugin-prod

Copy link
Copy Markdown
🤖 Jobs for this PR can be triggered through checkboxes. 🚧

ℹ️ To trigger the CI, please tick the checkbox below 👇

  • Click to trigger kibana-pull-request for this PR!
  • Click to trigger kibana-deploy-project-from-pr for this PR!
  • Click to trigger kibana-deploy-cloud-from-pr for this PR!
  • Click to trigger kibana-entity-store-performance-from-pr for this PR!
  • Click to trigger kibana-storybooks-from-pr for this PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants