Skip to content

[Cases] More workflow steps#256922

Merged
janmonschke merged 56 commits into
elastic:mainfrom
janmonschke:cases/workflow-steps-more-steps
Mar 30, 2026
Merged

[Cases] More workflow steps#256922
janmonschke merged 56 commits into
elastic:mainfrom
janmonschke:cases/workflow-steps-more-steps

Conversation

@janmonschke
Copy link
Copy Markdown
Contributor

@janmonschke janmonschke commented Mar 10, 2026

Summary

Implements https://github.com/elastic/security-team/issues/15084

This PR adds the following new cases steps:

  • cases.addAlerts
  • cases.addEvents
  • cases.addObservabled
  • cases.addTags
  • cases.assignCase
  • cases.deleteCases
  • cases.findCases
  • cases.findSimilarCases
  • cases.setCategory
  • cases.setCustomField
  • cases.setDescription
  • cases.setSeverity
  • cases.setStatus
  • cases.setTitle
  • cases.unassignCase
  • cases.updateCases

It also updates the existing case steps with some refactorings.

cases.setCustomField is disabled for now since we are waiting on a fix from a workflow team for that.

Testing

Use the following test workflow that should test all of the new steps. Play around with it. cases.closeCase is not in the kitchen-sink because it interferes with cases.addAlerts and cases.addEvents. You will have to update the alert, assignee and event properties for your env.

Click to expand workflow yaml
version: "1"
name: "cases.kitchen_sink"
description: "Kitchen-sink workflow that exercises all Cases workflow steps."
enabled: true
tags: [ "cases", "kitchen-sink", "example" ]
triggers:
  - type: manual

inputs:
  - name: owner
    type: string
    required: false
    default: "securitySolution"
    description: "Case owner used when creating the first case."
  - name: case_title
    type: string
    required: false
    default: "Kitchen sink workflow case"
    description: "Title for the case created by cases.createCase."
  - name: case_description
    type: string
    required: false
    default: "Created by the cases.kitchen_sink workflow example."
    description: "Description for the case created by cases.createCase."

steps:
  - name: create_case
    type: cases.createCase
    with:
      title: "{{ inputs.case_title }}"
      description: "{{ inputs.case_description }}"
      owner: "{{ inputs.owner }}"
      tags:
        - "kitchen-sink"
        - "workflows"
      severity: low
      settings:
        syncAlerts: false
        extractObservables: false
        

  - name: get_created_case
    type: cases.getCase
    with:
      case_id: "${{ steps.create_case.output.case.id }}"
      include_comments: false

  - name: update_created_case
    type: cases.updateCase
    with:
      case_id: "${{ steps.get_created_case.output.case.id }}"
      updates:
        title: "Updated: {{ inputs.case_title }}"
        description: "Updated by cases.updateCase in kitchen-sink workflow."
        severity: medium
        status: in-progress

  - name: add_comment_to_case
    type: cases.addComment
    with:
      case_id: "${{ steps.update_created_case.output.case.id }}"
      comment: "Kitchen-sink workflow comment added via cases.addComment."
  # - name: set_custom_field
  #   type: cases.setCustomField
  #   with:
  #     case_id: "${{steps.add_comment_to_case.output.case.id}}"
  #     field_name: cb6e9948-09ca-4ec6-8ebf-68de45f851e4
  #     value: true
  - name: find_similar
    type: cases.findSimilarCases
    with:
      case_id: "${{ steps.update_created_case.output.case.id }}"
      page: 1
      perPage: 20
  - name: find_cases
    type: cases.findCases
    with:
      owner: securitySolution
      page: 1
      perPage: 20
  - name: case_add_tags
    type: cases.addTags
    with:
      case_id: "${{ steps.update_created_case.output.case.id }}"
      tags:
        - added_afterwards
  - name: set_cat
    type: cases.setCategory
    with:
      case_id: "${{ steps.case_add_tags.output.case.id }}"
      version: "${{ steps.case_add_tags.output.case.version }}"
      category: test_cat
  - name: set_description
    type: cases.setDescription
    with:
      case_id: "${{steps.case_add_tags.output.case.id}}"
      version: "${{steps.set_cat.output.case.version}}"
      description: "setting with setDescription"
  - name: assign
    type: cases.assignCase
    with:
      case_id: "${{steps.set_description.output.case.id}}"
      version: "${{steps.set_description.output.case.version}}"
      assignees: 
        - uid: "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0"
  - name: unassign
    type: cases.unassignCase
    with:
      case_id: "${{steps.assign.output.case.id}}"
      assignees: null
  - name: add_alert
    type: cases.addAlerts
    with:
      case_id: "${{steps.unassign.output.case.id}}"
      alerts:
        - alertId: "b915cc436f17337771d5c1f91ab20906b4a001a8a7ab496ee9e2e1c643eab599"
          index: ".internal.alerts-security.alerts-default-000001"
          rule:
            id: "2ab7576e-b676-4e4a-9ed7-dbee1bab9f86"
            name: "Custom"
  - name: add_events
    type: cases.addEvents
    with:
      case_id: "${{steps.add_alert.output.case.id}}"
      events:
        - eventId: AZziMFnfH5twofAXPjsY
          index: .ds-logs-endpoint.events.process-default-2026.03.12-000001

@janmonschke janmonschke added release_note:enhancement backport:skip This PR does not require backporting Team:Cases Security Solution Cases team labels Mar 10, 2026
@janmonschke janmonschke changed the title [DRAFT][Cases] More workflow steps more [DRAFT][Cases] More workflow steps Mar 11, 2026
Copy link
Copy Markdown
Contributor

@semd semd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! awesome set of steps 🚀

I only spotted one problem:

Comment thread x-pack/platform/plugins/shared/cases/server/workflows/index.ts
Copy link
Copy Markdown
Contributor

@semd semd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!

Copy link
Copy Markdown
Contributor

@christineweng christineweng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took another pass and LGTM - I suggest updating the alert and event max constant before merge

Comment thread x-pack/platform/plugins/shared/cases/common/workflows/steps/add_alerts.ts Outdated
Comment thread x-pack/platform/plugins/shared/cases/common/workflows/steps/add_events.ts Outdated
Comment thread x-pack/platform/plugins/shared/cases/common/workflows/steps/find_similar_cases.ts Outdated

const SimilaritySchema = z.object({
typeKey: z.string(),
typeLabel: z.string(),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor flagged that typeLabel could be undefined, but I think we should address the missing label better (separately)

return {
typeKey,
value,
typeLabel: availableObservableTypes.get(typeKey)?.label,
};

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think for now we should be good, wdyt?

.array(
z.discriminatedUnion('type', [AlertCommentResponseProperties, UserCommentResponseProperties])
z.discriminatedUnion('type', [
ActionsCommentResponseProperties,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain why actions is added here? i think if the goal is to cover the existing schema, then external reference and persistable state should be added as well

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was added to unlock more autocompletion in the workflow editor. The other ones we can add later imo. Wdyt @christineweng ?

Copy link
Copy Markdown
Contributor

@christineweng christineweng Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline: I'm leaning towards not including actions, because it is legacy and will be gone in the v2 framework. but if we need it to get around validation, I'm okay with it..

patrykkopycinski added a commit to patrykkopycinski/kibana that referenced this pull request Mar 27, 2026
…findCases

Replace custom cases.attachAlert with cases.addAlerts from elastic#256922 (1:1 copy
for clean rebase). Add cases.findCases step to eliminate raw fetch() in
case_matching_step. Update pipeline YAML and step output format accordingly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Member

@nastasha-solomon nastasha-solomon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few language suggestions for copy in the defaultMessage field. They also apply to the other messages if that copy displays in the UI instead of API responses.

Comment thread x-pack/platform/plugins/shared/cases/common/workflows/translations.ts Outdated
Comment thread x-pack/platform/plugins/shared/cases/common/workflows/translations.ts Outdated
@janmonschke janmonschke enabled auto-merge (squash) March 30, 2026 08:58
@janmonschke janmonschke merged commit d0f463b into elastic:main Mar 30, 2026
18 checks passed
@elasticmachine
Copy link
Copy Markdown
Contributor

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
cases 2105 2117 +12

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
cases 2.0MB 2.0MB +13.1KB

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
cases 208.2KB 210.5KB +2.3KB
Unknown metric groups

async chunk count

id before after diff
cases 53 48 -5

History

patrykkopycinski added a commit to patrykkopycinski/kibana that referenced this pull request Mar 30, 2026
…findCases

Replace custom cases.attachAlert with cases.addAlerts from elastic#256922 (1:1 copy
for clean rebase). Add cases.findCases step to eliminate raw fetch() in
case_matching_step. Update pipeline YAML and step output format accordingly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
jeramysoucy pushed a commit to jeramysoucy/kibana that referenced this pull request Apr 1, 2026
## Summary

Implements elastic/security-team#15084

This PR adds the following new cases steps:

- `cases.addAlerts`
- `cases.addEvents`
- `cases.addObservabled`
- `cases.addTags`
- `cases.assignCase`
- `cases.deleteCases`
- `cases.findCases`
- `cases.findSimilarCases`
- `cases.setCategory`
- `cases.setCustomField`
- `cases.setDescription`
- `cases.setSeverity`
- `cases.setStatus`
- `cases.setTitle`
- `cases.unassignCase`
- `cases.updateCases`

It also updates the existing case steps with some refactorings.

`cases.setCustomField` is disabled for now since we are waiting on a fix
from a workflow team for that.

## Testing 

Use the following test workflow that should test all of the new steps.
Play around with it. `cases.closeCase` is not in the kitchen-sink
because it interferes with `cases.addAlerts` and `cases.addEvents`. You
will have to update the alert, assignee and event properties for your
env.

<details>

<summary>Click to expand workflow yaml</summary>

```yaml
version: "1"
name: "cases.kitchen_sink"
description: "Kitchen-sink workflow that exercises all Cases workflow steps."
enabled: true
tags: [ "cases", "kitchen-sink", "example" ]
triggers:
  - type: manual

inputs:
  - name: owner
    type: string
    required: false
    default: "securitySolution"
    description: "Case owner used when creating the first case."
  - name: case_title
    type: string
    required: false
    default: "Kitchen sink workflow case"
    description: "Title for the case created by cases.createCase."
  - name: case_description
    type: string
    required: false
    default: "Created by the cases.kitchen_sink workflow example."
    description: "Description for the case created by cases.createCase."

steps:
  - name: create_case
    type: cases.createCase
    with:
      title: "{{ inputs.case_title }}"
      description: "{{ inputs.case_description }}"
      owner: "{{ inputs.owner }}"
      tags:
        - "kitchen-sink"
        - "workflows"
      severity: low
      settings:
        syncAlerts: false
        extractObservables: false
        

  - name: get_created_case
    type: cases.getCase
    with:
      case_id: "${{ steps.create_case.output.case.id }}"
      include_comments: false

  - name: update_created_case
    type: cases.updateCase
    with:
      case_id: "${{ steps.get_created_case.output.case.id }}"
      updates:
        title: "Updated: {{ inputs.case_title }}"
        description: "Updated by cases.updateCase in kitchen-sink workflow."
        severity: medium
        status: in-progress

  - name: add_comment_to_case
    type: cases.addComment
    with:
      case_id: "${{ steps.update_created_case.output.case.id }}"
      comment: "Kitchen-sink workflow comment added via cases.addComment."
  # - name: set_custom_field
  #   type: cases.setCustomField
  #   with:
  #     case_id: "${{steps.add_comment_to_case.output.case.id}}"
  #     field_name: cb6e9948-09ca-4ec6-8ebf-68de45f851e4
  #     value: true
  - name: find_similar
    type: cases.findSimilarCases
    with:
      case_id: "${{ steps.update_created_case.output.case.id }}"
      page: 1
      perPage: 20
  - name: find_cases
    type: cases.findCases
    with:
      owner: securitySolution
      page: 1
      perPage: 20
  - name: case_add_tags
    type: cases.addTags
    with:
      case_id: "${{ steps.update_created_case.output.case.id }}"
      tags:
        - added_afterwards
  - name: set_cat
    type: cases.setCategory
    with:
      case_id: "${{ steps.case_add_tags.output.case.id }}"
      version: "${{ steps.case_add_tags.output.case.version }}"
      category: test_cat
  - name: set_description
    type: cases.setDescription
    with:
      case_id: "${{steps.case_add_tags.output.case.id}}"
      version: "${{steps.set_cat.output.case.version}}"
      description: "setting with setDescription"
  - name: assign
    type: cases.assignCase
    with:
      case_id: "${{steps.set_description.output.case.id}}"
      version: "${{steps.set_description.output.case.version}}"
      assignees: 
        - uid: "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0"
  - name: unassign
    type: cases.unassignCase
    with:
      case_id: "${{steps.assign.output.case.id}}"
      assignees: null
  - name: add_alert
    type: cases.addAlerts
    with:
      case_id: "${{steps.unassign.output.case.id}}"
      alerts:
        - alertId: "b915cc436f17337771d5c1f91ab20906b4a001a8a7ab496ee9e2e1c643eab599"
          index: ".internal.alerts-security.alerts-default-000001"
          rule:
            id: "2ab7576e-b676-4e4a-9ed7-dbee1bab9f86"
            name: "Custom"
  - name: add_events
    type: cases.addEvents
    with:
      case_id: "${{steps.add_alert.output.case.id}}"
      events:
        - eventId: AZziMFnfH5twofAXPjsY
          index: .ds-logs-endpoint.events.process-default-2026.03.12-000001
```

</details>

---------

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
paulinashakirova pushed a commit to paulinashakirova/kibana that referenced this pull request Apr 2, 2026
## Summary

Implements elastic/security-team#15084

This PR adds the following new cases steps:

- `cases.addAlerts`
- `cases.addEvents`
- `cases.addObservabled`
- `cases.addTags`
- `cases.assignCase`
- `cases.deleteCases`
- `cases.findCases`
- `cases.findSimilarCases`
- `cases.setCategory`
- `cases.setCustomField`
- `cases.setDescription`
- `cases.setSeverity`
- `cases.setStatus`
- `cases.setTitle`
- `cases.unassignCase`
- `cases.updateCases`

It also updates the existing case steps with some refactorings.

`cases.setCustomField` is disabled for now since we are waiting on a fix
from a workflow team for that.

## Testing 

Use the following test workflow that should test all of the new steps.
Play around with it. `cases.closeCase` is not in the kitchen-sink
because it interferes with `cases.addAlerts` and `cases.addEvents`. You
will have to update the alert, assignee and event properties for your
env.

<details>

<summary>Click to expand workflow yaml</summary>

```yaml
version: "1"
name: "cases.kitchen_sink"
description: "Kitchen-sink workflow that exercises all Cases workflow steps."
enabled: true
tags: [ "cases", "kitchen-sink", "example" ]
triggers:
  - type: manual

inputs:
  - name: owner
    type: string
    required: false
    default: "securitySolution"
    description: "Case owner used when creating the first case."
  - name: case_title
    type: string
    required: false
    default: "Kitchen sink workflow case"
    description: "Title for the case created by cases.createCase."
  - name: case_description
    type: string
    required: false
    default: "Created by the cases.kitchen_sink workflow example."
    description: "Description for the case created by cases.createCase."

steps:
  - name: create_case
    type: cases.createCase
    with:
      title: "{{ inputs.case_title }}"
      description: "{{ inputs.case_description }}"
      owner: "{{ inputs.owner }}"
      tags:
        - "kitchen-sink"
        - "workflows"
      severity: low
      settings:
        syncAlerts: false
        extractObservables: false
        

  - name: get_created_case
    type: cases.getCase
    with:
      case_id: "${{ steps.create_case.output.case.id }}"
      include_comments: false

  - name: update_created_case
    type: cases.updateCase
    with:
      case_id: "${{ steps.get_created_case.output.case.id }}"
      updates:
        title: "Updated: {{ inputs.case_title }}"
        description: "Updated by cases.updateCase in kitchen-sink workflow."
        severity: medium
        status: in-progress

  - name: add_comment_to_case
    type: cases.addComment
    with:
      case_id: "${{ steps.update_created_case.output.case.id }}"
      comment: "Kitchen-sink workflow comment added via cases.addComment."
  # - name: set_custom_field
  #   type: cases.setCustomField
  #   with:
  #     case_id: "${{steps.add_comment_to_case.output.case.id}}"
  #     field_name: cb6e9948-09ca-4ec6-8ebf-68de45f851e4
  #     value: true
  - name: find_similar
    type: cases.findSimilarCases
    with:
      case_id: "${{ steps.update_created_case.output.case.id }}"
      page: 1
      perPage: 20
  - name: find_cases
    type: cases.findCases
    with:
      owner: securitySolution
      page: 1
      perPage: 20
  - name: case_add_tags
    type: cases.addTags
    with:
      case_id: "${{ steps.update_created_case.output.case.id }}"
      tags:
        - added_afterwards
  - name: set_cat
    type: cases.setCategory
    with:
      case_id: "${{ steps.case_add_tags.output.case.id }}"
      version: "${{ steps.case_add_tags.output.case.version }}"
      category: test_cat
  - name: set_description
    type: cases.setDescription
    with:
      case_id: "${{steps.case_add_tags.output.case.id}}"
      version: "${{steps.set_cat.output.case.version}}"
      description: "setting with setDescription"
  - name: assign
    type: cases.assignCase
    with:
      case_id: "${{steps.set_description.output.case.id}}"
      version: "${{steps.set_description.output.case.version}}"
      assignees: 
        - uid: "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0"
  - name: unassign
    type: cases.unassignCase
    with:
      case_id: "${{steps.assign.output.case.id}}"
      assignees: null
  - name: add_alert
    type: cases.addAlerts
    with:
      case_id: "${{steps.unassign.output.case.id}}"
      alerts:
        - alertId: "b915cc436f17337771d5c1f91ab20906b4a001a8a7ab496ee9e2e1c643eab599"
          index: ".internal.alerts-security.alerts-default-000001"
          rule:
            id: "2ab7576e-b676-4e4a-9ed7-dbee1bab9f86"
            name: "Custom"
  - name: add_events
    type: cases.addEvents
    with:
      case_id: "${{steps.add_alert.output.case.id}}"
      events:
        - eventId: AZziMFnfH5twofAXPjsY
          index: .ds-logs-endpoint.events.process-default-2026.03.12-000001
```

</details>

---------

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:skip This PR does not require backporting release_note:enhancement Team:Cases Security Solution Cases team Team:One Workflow Team label for One Workflow (Workflow automation) v9.4.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants