Skip to content

Commit

Permalink
docs: add reaction docs (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
cugu authored Jul 21, 2024
1 parent 0c74f10 commit b21911e
Show file tree
Hide file tree
Showing 26 changed files with 365 additions and 22 deletions.
7 changes: 6 additions & 1 deletion docs/catalyst/admin/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Catalyst is a self-hosted application.
You can install it on your own server or use a cloud provider.

The latest release can be found on the [GitHub releases page](https://github.com/SecurityBrewery/catalyst/releases).
The release contains a binary for Linux, and macOS.
The releases contain binaries for Linux and macOS.

Once you have downloaded the binary, and unpacked it, you can start Catalyst with `cataylst serve`.

Expand All @@ -17,6 +17,11 @@ Open it and create an admin account.

In the admin UI create users which can then log in to the user interface at http://127.0.0.1:8090/.

## Configuration

At `Settings -> Application` you can configure the `Application URL` and set it to the URL where Catalyst is reachable.
This is important for Python actions to work correctly.

## Going to production

As Catalyst is based on PocketBase you can follow their
Expand Down
2 changes: 1 addition & 1 deletion docs/catalyst/admin/login.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ sidebar_position: 20

# Login

The admin login is located at the path `/_/` of your Catalyst instance,
The admin login is located at the path `https://<catalyst_url>/_/` of your Catalyst instance,
e.g. `https://try.catalyst.security-brewery.com/_/` for the demo instance.

Credentials can be set when your first start Catalyst or via the `catalyst admin` CLI command.
7 changes: 7 additions & 0 deletions docs/catalyst/admin/webhooks.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
---
sidebar_position: 50
sidebar_class_name: hidden
---

# Webhooks

Catalyst can send webhooks to other systems.
This can be used to trigger actions in other systems and create automated workflows.

:::warning

Admin webhooks are deprecated.
Use [reactions](../engineer/reactions) instead.
:::

## Configuration

Webhooks can be configured in the [admin interface](login.md), in the `webhooks` collection.
Expand Down
2 changes: 1 addition & 1 deletion docs/catalyst/analyst/_category_.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"label": "Analyst Handbook",
"position": 10,
"position": 40,
"collapsed": false,
"link": {
"type": "generated-index",
Expand Down
5 changes: 5 additions & 0 deletions docs/catalyst/engineer/reaction/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"label": "Reactions",
"position": 20,
"collapsed": false
}
9 changes: 9 additions & 0 deletions docs/catalyst/engineer/reaction/action/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"label": "Action",
"position": 40,
"collapsed": false,
"link": {
"type": "generated-index",
"description": "Actions can be used to automate Catalyst"
}
}
53 changes: 53 additions & 0 deletions docs/catalyst/engineer/reaction/action/python.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
sidebar_position: 10
---

# Python

Python action is a type of action that allows you to run Python code in response to a trigger.
You can use this action to perform any kind of operation that can be done using Python code.

:::warning

Python action is a powerful feature and can be used to perform any kind of operation on your data.
The Python code is executed in the same environment as the Catalyst server,
so be careful with the code you write and who has access to it.
:::

[![Reactions](/screenshots/reaction_action_python.png)](/screenshots/reaction_action_python.png)

## Event Data

The Python action receives the event data from the trigger in the first argument.
The event data is a JSON object that contains the data related to the trigger event.

To parse the event data in the Python code, you can use the following code:

```python
import sys
import json

# Parse the ticket from the input and print the ticket id
ticket = json.loads(sys.argv[1])
print("id", ticket["record"]["id"])
```

## Authentication

The Python action provides a temporary `CATALYST_TOKEN` environment variable that can be used to authenticate with the
Catalyst API.
I can be used in combination with the [PocketBase Python SDK](https://github.com/vaphes/pocketbase)
to interact with the Catalyst API

```python
import os

from pocketbase import PocketBase

# Connect to the PocketBase server
client = PocketBase('http://127.0.0.1:8090')
client.auth_store.save(token=os.environ["CATALYST_TOKEN"])

# Get users
users = client.collection("users").get_list(1, 200)
```
8 changes: 8 additions & 0 deletions docs/catalyst/engineer/reaction/action/webhook.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
sidebar_position: 20
---

# HTTP / Webhook


[![Reactions](/screenshots/reaction_action_webhook.png)](/screenshots/reaction_action_webhook.png)
9 changes: 9 additions & 0 deletions docs/catalyst/engineer/reaction/examples/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"label": "Examples",
"position": 60,
"collapsed": false,
"link": {
"type": "generated-index",
"description": "Examples of how to use Catalyst reactions."
}
}
36 changes: 36 additions & 0 deletions docs/catalyst/engineer/reaction/examples/assign_ticket.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
sidebar_position: 10
---

# Assign new tickets to random users

The following Python script assigns new tickets to random users in the system.
It can be combined with a [collection hook](../trigger/hook.md) that triggers on ticket creation.
After a ticket is created,
the hook will pass the ticket data to the Python action,
which will assign the ticket to a random user.

```python
import sys
import json
import random
import os

from pocketbase import PocketBase

# Parse the ticket from the input
ticket = json.loads(sys.argv[1])

# Connect to the PocketBase server
client = PocketBase('http://127.0.0.1:8090')
client.auth_store.save(token=os.environ["CATALYST_TOKEN"])

# Get a random user
users = client.collection("users").get_list(1, 200)
random_user = random.choice(users.items)

# Assign the ticket to the random user
client.collection("tickets").update(ticket["record"]["id"], {
"owner": random_user.id,
})
```
34 changes: 34 additions & 0 deletions docs/catalyst/engineer/reaction/examples/ingest_alerts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
sidebar_position: 5
---

# Ingest Alerts

This example demonstrates how to ingest alerts from a webhook into a PocketBase collection.

The trigger for this example is a [webhook trigger](../trigger/webhook.md) that receives alerts from an external system.
The webhook trigger passes a JSON event to the [Python action](../action/python.md) that contains the alert data.
The alert data is then used to create a new alert ticket.

```python
import sys
import json
import os

from pocketbase import PocketBase

# Parse the event from the webhook payload
event = json.loads(sys.argv[1])
body = json.loads(event["body"])

# Connect to the PocketBase server
client = PocketBase('http://127.0.0.1:8090')
client.auth_store.save(token=os.environ["CATALYST_TOKEN"])

# Create a new ticket
client.collection("tickets").create({
"name": body["name"],
"type": "alert",
"open": True,
})
```
27 changes: 27 additions & 0 deletions docs/catalyst/engineer/reaction/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
sidebar_position: 10
collapsed: false
---

# Reactions

Reactions are a way to trigger actions based on events.
Each reaction is composed of a trigger and an action.
The trigger listens for events and the action is executed when the trigger is activated.

[![Reactions](/screenshots/reactions.png)](/screenshots/reactions.png)

## Triggers

- [HTTP / Webhook](./trigger/webhook): Trigger an action on an incoming HTTP request.
- [Collection Hook](./trigger/hook): Trigger an action on events (`create`, `update`, `delete`) on a collection.

## Actions

- [Python](./action/python): Execute a Python script.
- [HTTP / Webhook](./action/webhook): Send an HTTP request to a webhook URL.

## Examples

- [Assign new tickets to random users](./examples/assign_ticket): Assign new tickets to random users.
- [Ingest alerts](./examples/ingest_alerts): Ingest alerts from a webhook into a PocketBase collection.
9 changes: 9 additions & 0 deletions docs/catalyst/engineer/reaction/trigger/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"label": "Trigger",
"position": 20,
"collapsed": false,
"link": {
"type": "generated-index",
"description": "Trigger can reaction to events in Catalyst and start actions"
}
}
71 changes: 71 additions & 0 deletions docs/catalyst/engineer/reaction/trigger/hook.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
sidebar_position: 10
---

# Collection Hook

A collection hook is a trigger that is executed when a record in a collection is created, updated, or deleted.
Collections are `Tickets`, `Tasks`, `Comments`, `Timeline`, `Links`, and `Files`.
You can add multiple collections and events to a collection hook.

[![Reactions](/screenshots/reaction_trigger_hook.png)](/screenshots/reaction_trigger_hook.png)

## Event Format

Collection hooks pass a json event to the action.

The following is an example of a `create` event for a ticket by a non-admin user:

```json
{
"action": "create",
"collection": "tickets",
"record": {
"collectionId": "tickets",
"collectionName": "tickets",
"created": "2024-07-07 01:31:02.110Z",
"description": "",
"id": "a0152zdnfzgow4z",
"name": "test",
"open": true,
"updated": "2024-07-07 01:31:02.110Z"
},
"auth": {
"avatar": "",
"collectionId": "_pb_users_auth_",
"collectionName": "users",
"created": "2024-07-07 01:29:57.912Z",
"emailVisibility": false,
"id": "u_test",
"name": "Alivia Cartwright",
"updated": "2024-07-07 01:29:57.912Z",
"username": "u_test",
"verified": true
}
}
```

The following is an example of an `update` event for a ticket by an admin user:

```json
{
"action": "update",
"collection": "tickets",
"record": {
"collectionId": "tickets",
"collectionName": "tickets",
"created": "2024-07-07 00:15:57.007Z",
"description": "",
"id": "tp0tppxc18slt9a",
"name": "my ticket",
"open": true,
"updated": "2024-07-07 00:15:57.007Z"
},
"admin": {
"id": "k72zfucb9kqmjyx",
"created": "2024-07-06 23:48:03.137Z",
"updated": "2024-07-06 23:48:03.137Z",
"username": "admin"
}
}
```
59 changes: 59 additions & 0 deletions docs/catalyst/engineer/reaction/trigger/webhook.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
sidebar_position: 5
---

# HTTP / Webhook

The HTTP/Webhook trigger allows you to trigger a reaction when a webhook is received.
This trigger is useful when you want to trigger a reaction based on an event that occurs in an external system.

HTTP/Webhook triggers require a path to listen on.
The URL to trigger the reaction is generated based on the path you provide,
e.g. if you provide the path `/webhook`,
the URL to trigger the reaction will be `https://<catalyst_url>/reaction/webhook`.

You can additionally provide a secret token to secure the webhook.
The secret token is used to verify that the webhook request is coming from a trusted source.
It needs to be provided in the `Authorization: Bearer <token>` header of the HTTP request,
e.g. `Authorization: Bearer my_secret_token`.

The reaction editor will show an example URL that you can use to trigger the reaction.

[![Reactions](/screenshots/reaction_trigger_webhook.png)](/screenshots/reaction_trigger_webhook.png)

## Event Data

The HTTP/Webhook trigger passes a JSON event to the action.

The following is an example of a webhook event:

```json
{
"method": "POST",
"path": "/webhook",
"headers": [],
"query": [],
"body": "{\"name\": \"test\"}",
"isBase64Encoded": false
}
```

## Response Data

If the action returns a response, the response will be sent back to the webhook source.

For simple text responses, the response will be sent back as the body of the response.
If the action returns a JSON response, in the following format, it will be used to construct the response:

```json
{
"statusCode": 200,
"headers": {
"Content-Type": [
"application/json"
]
},
"body": "{\"message\": \"success\"}",
"isBase64Encoded": false
}
```
Loading

0 comments on commit b21911e

Please sign in to comment.