# Custom Webhook Destination

## Overview

Destinations are integrations that receive alerts from rules, policies, system health notifications, and rule errors. Panther supports configuring a Custom Webhook as the destination where you will receive alerts.

A Custom Webhook Destination requires only a `URL` to the service which can accept an HTTP `POST` request containing a `JSON` payload. This destination type is designed to allow Panther to communicate with other third-party integrations.

## How to set up a Custom Webhook alert destination in Panther

### Authenticating webhook calls from Panther

To pass authentication credentials to the delivery location with webhook calls from Panther, you can add custom HTTP headers. During [webhook setup](#set-up-a-custom-webhook-in-panther), add one or more **Header Name** / **Header Value** pairs.

### Delivery and Ack

The webhook must accept and acknowledge Panther's `POST` request with an HTTP status code in the `2XX` range. If there were any network failures or non `2XX` codes, Panther will attempt to retry the request up to ten (10) times before permanent failure.

The webhook response body will be stored in the delivery status which can be viewed in the Alert Details page.

In the event of a permanent delivery failure, Panther logs and provides workflow continuity by allowing the alert to be manually re-sent by visiting the Alert Details page and viewing the Delivery Status section.

### Set up a custom webhook in Panther

1. Log in to the Panther Console.
2. On the left sidebar click **Configure > Alert Destinations**.
3. Click **+Add your first Destination**.
   * If you have already created Destinations, click **Create New** in the upper right side of the page to add a new Destination.
4. Click **Custom Webhook**.
5. Fill out the form:
   * **Display Name**: Add a friendly name to identify your destination.
   * **Custom Webhook URL**: Enter your Custom Webhook forwarding URL.
     * If you follow [the ngrok example](#custom-webhook-example) later in this documentation, you would enter the `http` or `https` **Forwarding** URL from the `ngrok` output.
   * **Severity Levels**: Select the severity level of alerts to send to this Destination.
   * **Default Alert Types**: Select the alert types to send to this Destination.
   * **Log Types**: By default, we will send alerts from all log types. Specify log types here if you want to only send alerts from specific log types.
   * **Allow Manual Dispatch**: Set this toggle ON if you'd like to be able to [manually dispatch alerts](https://docs.panther.com/alerts#manual-alert-dispatch) to this destination.\
     ![In the Panther Console, the "Configure your Custom Webhook Destination" page is displayed. It contains fields for Display Name, Custom Webhook URL, Severity, Alert Types, and Log Types.](https://4011785613-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LgdiSWdyJcXPahGi9Rs-2910905616%2Fuploads%2Fgit-blob-8e188f7744fc15b555724ac79f1fcfaa467c6f5c%2FScreen%20Shot%202022-08-31%20at%2011.28.01.png?alt=media)
   * **Custom HTTP Headers**: Optionally provide one or more custom HTTP headers to be included with the POST request that sends the alerts.\
     ![Next to "Add custom HTTP headers?" the toggle is set to "yes."](https://4011785613-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LgdiSWdyJcXPahGi9Rs-2910905616%2Fuploads%2Fgit-blob-83ab7562c0ddf9356b1d42d3c7210579f6bf60c4%2Fimage.png?alt=media)
6. Click **Add Destination**.
7. On the final page, optionally click **Send Test Alert** to test the integration using a test payload. When you are finished, click **Finish Setup**.

<figure><img src="https://4011785613-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LgdiSWdyJcXPahGi9Rs-2910905616%2Fuploads%2Fgit-blob-36c350cbbc4624e1ee9632f5c8fad969e128034d%2Fwebhook3.png?alt=media" alt="The screen displays a large green circle with a checkmark in it. A message at the top says &#x22;Everything looks good!&#x22; There is a blue button at the button labeled &#x22;Send Test Alert&#x22; and below that there is a link labeled &#x22;Finish Setup.&#x22;" width="563"><figcaption></figcaption></figure>

### Custom Webhook alert schema

A Custom Webhook will deliver a payload containing the following fields:

<table><thead><tr><th width="172">Field</th><th width="121.33333333333331">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>id</code></td><td><code>string</code></td><td>Identifier of the alert's detection</td></tr><tr><td><code>createdAt</code></td><td><code>string</code></td><td>Alert creation time as AWSDateTime (ISO-8601)</td></tr><tr><td><code>severity</code></td><td><code>string</code></td><td>Severity of the alert</td></tr><tr><td><code>type</code></td><td><code>string</code></td><td>Type of the alert</td></tr><tr><td><code>link</code></td><td><code>string</code></td><td>Link to the alert in the Panther Console</td></tr><tr><td><code>title</code></td><td><code>string</code></td><td>Title of the alert</td></tr><tr><td><code>name</code></td><td><code>string</code></td><td>Name of the alert's detection</td></tr><tr><td><code>alertId</code></td><td><code>string</code></td><td>Identifier of the alert in Panther Backend</td></tr><tr><td><code>description</code></td><td><code>string</code></td><td>Description associated with the alert</td></tr><tr><td><code>runbook</code></td><td><code>string</code></td><td>Runbook associated with the alert</td></tr><tr><td><code>tags</code></td><td><code>string[]</code></td><td>List of tags associated with the alert</td></tr><tr><td><code>version</code></td><td><code>string</code></td><td>Version identifier for the alert's detection</td></tr><tr><td><code>alertContext</code></td><td><code>object</code></td><td><a href="../../../detections/rules/python#alert_context">Alert Context</a> data attached to the alert</td></tr></tbody></table>

The [AWSDateTime](https://docs.aws.amazon.com/appsync/latest/devguide/scalars.html) scalar type represents a valid extended ISO 8601 DateTime string. In other words, this scalar type accepts datetime strings of the form `YYYY-MM-DDThh:mm:ss.sssZ`. The field after the seconds field is a nanoseconds field. It can accept between 1 and 9 digits. The seconds and nanoseconds fields are optional (the seconds field must be specified if the nanoseconds field is to be used). The time zone offset is compulsory for this scalar. The time zone offset must either be Z (representing the UTC time zone) or be in the format `±hh:mm:ss`. The seconds field in the timezone offset will be considered valid even though it is not part of the ISO 8601 standard.

#### Example JSON payload:

```json
{
  "id": "AllLogs.IPMonitoring",
  "createdAt": "2020-10-13T03:35:24Z",
  "severity": "INFO",
  "type": "RULE",
  "link": "https://runpanther.io/alerts/b90c19e66e160e194a5b3b94ec27fb7c",
  "title": "New Alert: Suspicious traffic detected from [123.123.123.123]",
  "name": "Monitor Suspicious IPs",
  "alertId": "b90c19e66e160e194a5b3b94ec27fb7c",
  "alertContext": {
    "key": "value" // alertContext contents are configured on the detection
  },
  "description": "This rule alerts on any activity outside of our IP address whitelist",
  "runbook": "",
  "tags": [
    "Network Monitoring",
    "Threat Intel"
  ],
  "version": "CJm9PiaXV0q8U0JhoFmE6L21ou7e5Ek0"
}
```

## Custom Webhook example

The following example demonstrates sending Panther alerts to a custom webhook which forwards the payload to a simple [Node.js](https://nodejs.org/en/) server proxied via [Ngrok](https://ngrok.com/).

1. Open Command Line.
2. Create an [ngrok account](https://dashboard.ngrok.com/signup) and [install](https://ngrok.com/download) ngrok
   1. Run this config command: `ngrok config add-authtoken <token>`
   2. Run this command to start the service on port 8081: `ngrok http 8081`
3. [Install Node.js](https://nodejs.org/en/download).
4. Create a file, `webhook.js`, and paste the following snippet:

   ```javascript
   const http = require('http')
   const util = require('util')
   const port = 8081

   const requestHandler = (req, res) => {

     if (req.method === 'POST') {
       let body = '';
       req.on('data', chunk => {
         body += chunk.toString();
       });
       req.on('end', () => {
         console.log(util.inspect(JSON.parse(body), false, null, true));
         res.statusCode = 200; // Must ack the request
         res.end("success"); // (Optional) response body
       });
     }
   }

   const server = http.createServer(requestHandler)

   server.listen(port, (err) => {
     if (err) {
       return console.log('something bad happened', err)
     }

     console.log(`server is listening on ${port}`)
   })
   ```
5. Open another terminal and start the Node.js server:

   ```shell
   > node webhook.js
   server is listening on 8081
   ```
6. In the **Panther Console**, create a new **Custom Webhook** and paste the **Forwarding** URL from `ngrok` into the **Custom Webhook URL** field.
   * For example, the forwarding URL might look like: `https://2d9c-174-27-211-147.ngrok-free.app`
7. Click **Send a test alert** to see that the node.js server logs the test event.

## Additional Information on Destinations

For more information on alert routing order, modifying or deleting destinations, and workflow automation, please see the Panther docs: [Destinations](https://docs.panther.com/destinations).
