Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Replacing SOAR Workflows

Most SOAR deployments run a handful of playbooks that are, underneath, a sequence of API calls with some branching. The platform around them exists to schedule those calls, store credentials, and show a diagram. That platform is also a second thing: a second install, a second database, a second copy of your data, a second bill on top of what you already pay Splunk for.

If your data is already in Splunk and your triggers are already Splunk alerts, much of that platform is doing work you are also paying Splunk to do -- on infrastructure you did not need to stand up in the first place.

Where It Actually Runs

This is the difference that the rest of this page follows from, so it is worth stating plainly before anything else. SOAR is a separate platform. It has its own install, its own database, its own upgrade cycle, and its own estate to size, patch and back up, sitting next to Splunk rather than inside it. Every playbook run means your event left Splunk, arrived at that second platform, and got acted on there.

BabySOARus has none of that, because it is not a second platform. It ships as a Splunk app and runs its daemon on the hosts already running splunkd -- the search head, and (exec reports itself as distributable) the indexers too, if that is where you want the work done. There is no event export, no second copy of your data, and no new estate to operate: whatever already scales, patches and backs up Splunk already does the same for this. A detection and its response can be the same search.

An Honest Comparison

AspectSOAR platformBabySOARus
Where it runsIts own platform, installed and operated separatelyThe search heads (and indexers) you already run
Data movementCopied into the platformNever leaves Splunk
TriggerIngest events, correlate, fireThe Splunk alert you already have
Playbook formatVisual graph, exported as JSONPython in version control
Testing a playbookPlatform's test harnessRun the search, or babysoarus-ci with no Splunk at all
Adding an integrationInstall or write an apphttp_request(...)
Integration trust modelA vendor's app, with whatever access the platform's asset model grants itYour own reviewed Python, sandboxed regardless of what it tries to do
Time to first versionDaysMinutes
Approval gatesBuilt inBuilt in (prompt.ask, an approval inbox with a full audit trail)
Execution visibilityA run history and a live status viewBuilt in (Activity's Tasks panel for the audit trail, Running now for what is executing this moment)
Case managementBuilt inWhatever you already use
Multi-tenancy, RBACBuilt inSplunk's
Visual diagram for auditorsYesNot yet -- see what's coming
Licence costSignificant, per analyst seatA flat per-deployment fee, not metered by use

Two rows in that table are still where SOAR genuinely wins outright: built-in case management and a diagram an auditor will accept today. If those matter to you on their own, keep the platform for them specifically -- see when to keep SOAR below, which is narrower than it used to be.

What BabySOARus changes is the calculation for teams whose playbooks are "enrich, decide, call three APIs, open a ticket". That is most playbooks.

The Same Playbook, Both Ways

Playbook: phishing URL reported by a user.

In a SOAR platform: a graph of nine blocks, each configured through a form, connected by conditional edges, with an app installed for each integration.

Here:

for e in events:
    url = e['reported_url']

    # 1. Detonate.
    r = http_request('POST', f'{SANDBOX}/api/v2/submit',
                     headers={'Authorization': 'Bearer ' + sandbox_token},
                     body={'url': url, 'timeout': 60}, timeout=30)
    verdict = json.loads(r['body']) if r['status'] == 200 else {}
    e['sandbox_verdict'] = verdict.get('verdict', 'unknown')
    e['sandbox_score'] = verdict.get('score', 0)

    # 2. Who else got it?
    r = splunk_request('GET',
        '/services/search/jobs/export?output_mode=json&search='
        f'search index=email url="{url}" earliest=-7d | stats dc(recipient) as recipients')
    e['recipients'] = 0
    for line in r['body'].decode().splitlines():
        if line.strip():
            try:
                e['recipients'] = int(json.loads(line)['result']['recipients'])
            except (KeyError, ValueError):
                pass

    # 3. Decide.
    if e['sandbox_score'] > 70:
        e['decision'] = 'malicious'
    elif e['sandbox_score'] > 30 or e['recipients'] > 20:
        e['decision'] = 'review'
    else:
        e['decision'] = 'benign'

    # 4. Act.
    e['actions'] = []
    if e['decision'] == 'malicious':
        r = http_request('POST', f'{PROXY}/api/blocklist',
                         headers={'Authorization': 'Bearer ' + proxy_token},
                         body={'url': url, 'reason': 'phishing, sandbox confirmed'})
        e['actions'].append('blocked at proxy' if r['status'] < 300 else 'proxy block FAILED')

        r = http_request('POST', f'{EMAIL}/api/quarantine',
                         headers={'Authorization': 'Bearer ' + email_token},
                         body={'url': url, 'scope': 'all_mailboxes'})
        e['actions'].append('quarantined' if r['status'] < 300 else 'quarantine FAILED')

    # 5. Tell the reporter.
    http_request('POST', NOTIFY, body={
        'to': e['reporter'],
        'subject': f'Your phishing report: {e["decision"]}',
        'body': f"Thank you. Verdict: {e['decision']}. "
                f"Actions: {', '.join(e['actions']) or 'none required'}.",
    })

Forty lines, in Git, reviewable in a pull request, testable by running a search. The diagram is the code.

Performance, without a Number to Misuse

This page will not quote a benchmark figure for either platform, and that is deliberate: a number taken on one machine describes that machine, not yours, and a published figure invites exactly the wrong comparison. What can be said without a number is the architecture, and it does not need one to make the case.

A SOAR playbook action pays for leaving Splunk. The event is serialised, handed to a separate platform, picked up by that platform's own execution path, and (by design, since isolating one vendor's app from another is the point) very often started in an environment spun up for that action specifically. None of that is a flaw in SOAR -- it is what a general-purpose orchestration platform running arbitrary third-party apps has to do to stay safe. It is simply cost that exists because the work happens somewhere else.

BabySOARus never leaves. The daemon runs on the host already running your search, keeps a pool of interpreters already booted, and hands a batch of events to one directly -- there is no second platform to reach, no job queue to wait on, and for an enrichment step, no separate round trip to notice at all: the answer is already part of the search that asked for it. How the daemon keeps this warm is measured in microseconds rather than milliseconds for the overhead it adds beyond your own code, and published figures will appear there once they come from repeatable hardware rather than a laptop -- the same discipline this page holds itself to.

Security and the Supply Chain

A SOAR "app" is someone else's code, trusted with whatever the platform's asset model grants it. That is a reasonable trade for an app store's worth of pre-built integrations, but it is a real trust boundary: installing an integration means installing a vendor's Python, and its blast radius is whatever the platform lets an app reach.

BabySOARus's sandbox does not trust the code at all, including your own. Every function runs inside a WebAssembly component with no ambient access to anything -- no network, no filesystem beyond an explicit read-only mount, no process spawning -- until an explicit allow-list grants it. That holds regardless of whether the code came from your own git history or a built-in library entry: the sandbox does not know the difference, and does not need to trust either.

The same property that removes a second platform also removes a second thing to secure: there is no second database holding a copy of your events, no second set of credentials for it, and no second incident if that platform is the one that gets breached.

What You Lose

Be honest about this before proposing it.

No visual editor, yet. Someone who does not write code cannot modify a playbook today. For many teams that is a feature, but say so out loud -- and see what's coming for where this is headed.

No case management. You need somewhere to put cases. Most teams already have one, and http_request reaches it.

No built-in credential vault. Splunk's password store works and is reachable over REST, but it is not a purpose-built secrets manager.

No audit diagram. Approval gates carry a full record of who was asked, who answered and what ran as a result, but that is a log, not a picture. If a regulator specifically wants a diagram, code is not one.

What You Gain

Playbooks in version control. Diffs, reviews, blame, branches, rollback. Ask anyone who has tried to review a change to a visual playbook.

Testing that is just running it. Set DRY_RUN = True and execute the search. No separate test environment.

No data duplication. The playbook runs where the data already is. Nothing is copied into a second platform, which removes an entire class of "why does the SOAR show something different" problems.

Minutes, not days. New integration? It is an HTTP call. You do not need an app, a connector, or a vendor.

One skill. Detection engineers write Python for detections and Python for response. There is no second product to learn.

A Sensible Migration

Do not attempt a big-bang replacement.

Start with enrichment playbooks. They are read-only, so the blast radius is zero. Most SOAR deployments have several, and they are the easiest to move.

Then move notification playbooks. Also low risk, and immediately valuable because the notifications get better when they are code.

Then containment, in dry-run. Run alongside the platform and compare decisions for a few weeks.

Then switch the triggers. Turn off the platform's version once you have watched the replacement agree with it.

Keep the platform for what it is good at. Case management, a no-code editor for non-engineers, and a visual diagram a regulator wants to look at. Running three playbooks in a platform is a much smaller licence than running thirty.

What Is Coming, and What Is Not Yet

One row in the table above is marked "not yet" rather than "no" on purpose, and two more gaps beyond the table follow the same shape. All three are designed already, not merely hoped for, and all three are deliberately sequenced after the core -- licensing, the content library, the connector pattern -- rather than before it, so this section says plainly what exists today and what does not, instead of blurring the two.

A visual flow editor. Closes the "no-code" gap in the table above directly: a non-engineer building and adjusting a response flow without writing Python. Designed, not yet built.

A signed integrations catalogue. The one hand-built connector this product ships today (Microsoft Defender for Endpoint, both enrichment and response actions) already proves the pattern -- an HTTP call and a documented secret, not a from-scratch app -- works without a marketplace around it. The catalogue adds curation and per-integration access control on top of that same pattern, closing the breadth SOAR's own app store still wins on today. Designed, not yet built.

An agent-facing surface. AI agents already documents why this sandbox -- deny-by-default, no ambient access, a tool call that either succeeds within its grant or fails loudly -- is a genuinely good execution substrate for an LLM tool call, today, with what already exists. A dedicated UI for that workflow is on the same roadmap, and unlike the two gaps above, it is not chasing a capability SOAR already has: no SOAR platform offers an equivalent story for agentic investigation today.

None of the three above should be treated as available now. What already ships -- the sandbox, the editor, saved functions addressed by name, version history, testing without Splunk, the debugger, background tasks with a real task manager and audit trail, a live view of what is executing right now, notifications and a real approval gate with its own audit trail -- is real and is what the rest of this page describes.

When to Keep SOAR

Keep it if:

  • your triggers are not Splunk alerts;
  • non-engineers must edit playbooks today, not once the visual editor above ships;
  • you need case management and do not have another system;
  • you orchestrate across many products where the breadth of a mature app store is genuinely doing work you do not want to do yourself, today;
  • a regulator specifically requires a visual diagram, not a recorded log of who approved what.

Consider replacing it if:

  • your playbooks are mostly "enrich and notify";
  • your triggers are already Splunk alerts;
  • your team writes code comfortably;
  • you already have case management;
  • a recorded approval trail satisfies your compliance need, and a diagram specifically does not need to exist for it;
  • the licence is hard to justify against what it actually runs.

Practical Patterns

Credentials. Read them from Splunk's password store at run time. See Alert actions.

Idempotency. Alerts can fire twice. Key actions on something stable and check before acting.

r = http_request('GET', f'{CASES}/api/v1/cases?external_id={e["sid"]}')
if json.loads(r['body'])['total'] > 0:
    e['skipped'] = 'case already exists for this search id'
    continue

Rate limits. Batch by design. events is already a batch, so build one request from it rather than one per row.

Failure handling. Record what failed on the event itself and raise at the end, so a partial run is visible rather than silent.

Long-running actions. Do not block for minutes inside a snippet. Kick off the job, record its identifier, and let a second scheduled search collect the result.