Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 102 additions & 12 deletions docs/5-integrations/extensions/limacharlie/playbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

> LimaCharlie LABS

!!! warning "Python SDK v4 only"
The Playbook execution environment runs on the LimaCharlie **Python SDK v4**.
The recently released [Python SDK v5](../../../6-developer-guide/sdks/python-sdk.md)
is **not yet supported** in playbooks — write playbook code against v4 APIs.
See the [Python SDK v4 documentation](../../../6-developer-guide/sdks/python-sdk-v4.md)
for the supported `Manager` interface and module layout.
!!! note "Choosing the Python SDK version"
Each playbook runs on either the LimaCharlie [Python SDK v4](../../../6-developer-guide/sdks/python-sdk-v4.md)
(the default) or the [Python SDK v5](../../../6-developer-guide/sdks/python-sdk.md).
Existing playbooks keep running on v4. See [Python SDK version](#python-sdk-version) below to opt a playbook into v5.

The Playbook Extension allows you to execute Python playbooks within the context of your Organization in order to automate tasks and customize more complex detections.

Expand Down Expand Up @@ -60,6 +58,31 @@ Here is an example D&R rule starting a new invocation of a playbook.

### Python example

Using the Python SDK v5:

```python
from limacharlie.client import Client
from limacharlie.sdk.organization import Organization
from limacharlie.sdk.extensions import Extensions

# Client picks up credentials from the environment or ~/.limacharlie.d/config.yaml.
org = Organization(Client())

# Issue a request to the "ext-playbook" extension.
response = Extensions(org).request("ext-playbook", "run_playbook", {
"name": "my-playbook",
"credentials": "hive://secret/my-playbook-api-key",
"data": {
"some": "data"
}
})

# The returned data from the playbook.
print(response)
```

Using the Python SDK v4:

```python
import limacharlie

Expand All @@ -80,11 +103,13 @@ response = ext.request("ext-playbook", "run_playbook", {
print(response)
```

The SDK used to *call* a playbook is independent of the SDK the playbook itself runs on.

## Playbook structure

A playbook is a normal python script. The only required component is a top level function called `playbook` which takes 2 arguments:

- `sdk`: an instance of the LC Python SDK v4 `limacharlie.Manager`, pre-authenticated to the relevant Organization based on the credentials provided, if any, `None` otherwise.
- `sdk`: an instance of the LC Python SDK, pre-authenticated to the relevant Organization based on the credentials provided, if any, `None` otherwise. With SDK v4 (the default) it is a `limacharlie.Manager`; with SDK v5 it is a `limacharlie.sdk.organization.Organization`. See [Python SDK version](#python-sdk-version).
- `data`: the optional JSON dictionary provided as context to your playbook.

The function must return a dictionary with the following optional keys:
Expand All @@ -96,6 +121,48 @@ The function must return a dictionary with the following optional keys:

This allows your playbook to return information about its execution, return data, errors or generate a detection. The python `print()` statement is not currently being returned to the caller or otherwise accessible, so you will want to use the `data` in order to return information about the execution of your playbook.

### Python SDK version

The optional `sdk_version` field of the playbook record selects the Python SDK the playbook runs on:

| `sdk_version` | SDK | `sdk` argument |
|---|---|---|
| absent, `""` or `"4"` | [Python SDK v4](../../../6-developer-guide/sdks/python-sdk-v4.md) | `limacharlie.Manager` |
| `"5"` | [Python SDK v5](../../../6-developer-guide/sdks/python-sdk.md) | `limacharlie.sdk.organization.Organization` |

Any other value is rejected when the playbook is saved. In the web app, choose the version with the **Python SDK** selector in the playbook editor. Through the API, CLI or Infrastructure as Code, set `sdk_version` next to `python` in the record's data (see [Infrastructure as Code](#infrastructure-as-code)).

Things to know about SDK v5 playbooks:

- The value returned by `playbook()` must be JSON-serializable.
- The `is_interactive` request parameter is only supported with SDK v4. A request with `is_interactive` set to `true` for a v5 playbook is rejected.
- Each v5 execution runs in its own process, and anything the playbook started in the background is stopped when `playbook()` returns.

The following v5 playbook reads a secret and counts the Organization's sensors:

```python
from limacharlie.sdk.hive import Hive

def playbook(sdk, data):
if not sdk:
return {"error": "LC API key required"}

# Read a secret from the secret Hive.
my_secret = Hive(sdk, "secret").get("my-secret-name").data["secret"]

# Organization.list_sensors() is a v5 generator yielding sensor dicts.
sensors = [{"sid": s["sid"], "hostname": s.get("hostname")} for s in sdk.list_sensors()]

return {
"data": {
"oid": sdk.oid,
"sensor_count": len(sensors),
}
}
```

The examples below use SDK v4.

### Example playbook

The following is a sample playbook that sends a webhook to an external product with a secret stored in LimaCharlie, and it returns the data as the response from the playbook.
Expand Down Expand Up @@ -200,11 +267,10 @@ The current execution environment is based on the default libraries provided by

- Python
- `weasyprint`
- `flask`
- `gunicorn`
- `flask`
- `limacharlie` (LimaCharlie SDK/CLI)
- `lcextension` (LimaCharlie Extension SDK)
- `flask` (SDK v4 playbooks only)
- `gunicorn` (SDK v4 playbooks only)
- `limacharlie` (LimaCharlie SDK/CLI): v4 for SDK v4 playbooks, v5 for SDK v5 playbooks
- `lcextension` (LimaCharlie Extension SDK, SDK v4 playbooks only)
- `scikit-learn` (Python Machine Learning kit)
- `jinja2`
- `markdown`
Expand Down Expand Up @@ -242,6 +308,30 @@ hives:
comment: ""
```

To run a playbook on the Python SDK v5, add `sdk_version: "5"` to its data:

```yaml
hives:
playbook:
my-v5-playbook:
data:
sdk_version: "5"
python: |-
def playbook(sdk, data):
if not sdk:
return {"error": "LC API key required to list sensors"}
return {
"data": {
"sensors": list(sdk.list_sensors())
}
}
usr_mtd:
enabled: true
expiry: 0
tags: []
comment: ""
```

## Billing

Playbooks are billed per seconds of total execution time.
Loading