<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: implementing-soar-playbook-development
description: >-
  Build SOAR playbooks for automated incident handling including alert triage,
  enrichment, containment actions, notification routing, and case management
  with idempotent action steps and audit logging.
domain: cybersecurity
subdomain: security-operations-automation
tags:
  - soar
  - playbook
  - orchestration
  - automation
  - incident-handling
  - cortex-xsoar
  - shuffle
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: []
---

# Implementing SOAR Playbook Development

## Overview

SOAR playbooks codify incident response procedures as executable workflows.
Each playbook defines trigger conditions, decision logic, enrichment steps,
containment actions, and notification routing. Actions must be idempotent,
auditable, and fail-safe with rollback capabilities.

Mode: `[MODE: BLUE]` — Automated orchestration and response.

## Prerequisites

| Requirement | Details |
|---|---|
| Python 3.10+ with `requests`, `pyyaml` | Required |
| SOAR platform API access (Cortex XSOAR, Shuffle, or custom) | Required |
| SIEM webhook or polling integration for alert ingestion | Required |
| Ticketing system API (Jira, ServiceNow) for case management | Required |

## Key Concepts

### Playbook Structure

```python
PLAYBOOK_SCHEMA = {
    "name": "isolate-compromised-host",
    "trigger": {"type": "alert", "source": "edr", "severity": ["critical", "high"]},
    "steps": [
        {"action": "enrich_host", "input": "alert.hostname"},
        {"action": "check_asset_criticality", "input": "enrichment.asset_info"},
        {"action": "isolate_host", "condition": "asset.criticality != 'mission-critical'"},
        {"action": "create_ticket", "input": "alert + enrichment"},
        {"action": "notify_soc", "channel": "#incidents", "severity": "alert.severity"},
    ],
    "on_failure": {"action": "escalate", "tier": 2},
}
```

### Action Registry

```python
from typing import Any

ACTION_REGISTRY: dict[str, callable] = {}

def register_action(name: str):
    """Decorator to register a playbook action."""
    def decorator(func):
        ACTION_REGISTRY[name] = func
        return func
    return decorator

@register_action("enrich_host")
def enrich_host(hostname: str, context: dict) -> dict[str, Any]:
    """Look up host in CMDB and return asset details."""
    return {
        "hostname": hostname,
        "os": "Ubuntu 22.04",
        "criticality": "standard",
        "owner": "engineering",
        "last_scan": "2026-03-15T10:00:00Z",
    }
```

### Execution Engine

```python
import logging
from datetime import datetime, timezone

logger = logging.getLogger("soar.engine")

def execute_playbook(playbook: dict, alert: dict) -> dict:
    """Run a playbook against an alert with step-by-step audit logging."""
    execution_id = f"PB-{datetime.now(timezone.utc).strftime('%Y%m%d%H%M%S')}"
    results = {"execution_id": execution_id, "steps": [], "status": "running"}

    for step in playbook["steps"]:
        action_fn = ACTION_REGISTRY.get(step["action"])
        if not action_fn:
            logger.error("Unknown action: %s", step["action"])
            results["status"] = "failed"
            break

        try:
            result = action_fn(alert=alert, context=results)
            results["steps"].append({
                "action": step["action"],
                "status": "success",
                "timestamp": datetime.now(timezone.utc).isoformat(),
                "output": result,
            })
        except Exception as e:
            logger.error("Step %s failed: %s", step["action"], e)
            results["steps"].append({
                "action": step["action"],
                "status": "failed",
                "error": str(e),
            })
            results["status"] = "failed"
            break

    if results["status"] == "running":
        results["status"] = "completed"
    return results
```

## Workflow

### Step 1: Define Playbook

```bash
node scripts/agent.js --action list-playbooks
```

### Step 2: Execute Against Alert

```bash
node scripts/agent.js --action run-playbook --playbook isolate-host --alert-id ALT-001
```

### Step 3: Review Execution Log

```bash
node scripts/agent.js --action execution-log --execution-id PB-20260318
```

## Verification

- [ ] Playbook steps execute in order with audit trail
- [ ] Failed steps trigger on_failure handlers
- [ ] Actions are idempotent — repeated execution produces same result
- [ ] All actions logged with timestamp and execution ID

## References

- [Cortex XSOAR Playbook Guide](https://docs-cortex.paloaltonetworks.com/r/Cortex-XSOAR)
- [Shuffle SOAR Documentation](https://shuffler.io/docs)
- [NIST SP 800-61r2 — Incident Handling](https://csrc.nist.gov/publications/detail/sp/800-61/rev-2/final)
