# Webhook Integration

Configure LinuxGuard to deliver security signals to an HTTP endpoint using signed webhook requests.

## Prerequisites

* Access to the LinuxGuard console with administrator role
* An HTTPS endpoint that can receive POST requests (http\:// URLs are not accepted)

## Create a Webhook Endpoint

1. In the LinuxGuard console, navigate to **Settings** > **Integrations** > **Webhooks**.
2. Select **Add Endpoint**.
3. Enter the **URL** of your receiving endpoint.

   > **Note**: Only HTTPS URLs are accepted. Endpoints using `http://` are rejected at validation.
4. Enter a descriptive **Name** for the endpoint (for example, `security-siem-webhook`).
5. Optionally, add **Custom Headers** for authentication or routing (see [Custom Headers](#custom-headers)).
6. Select **Create**.

> **Important**: The webhook secret is displayed only once when the endpoint is created. Copy and store it securely before navigating away. If you lose the secret, you must delete and re-create the endpoint to generate a new one.

## Verify HMAC Signatures

Every webhook request includes a `LinuxGuard-Signature: sha256=<hex>` header. This value is an HMAC-SHA256 signature computed over the raw request body using the endpoint secret. Your receiver must validate this signature to confirm the request originated from LinuxGuard.

Use a timing-safe comparison function to prevent timing oracle attacks. The examples below use the standard timing-safe functions available in each language.

**Python**

```python
import hmac
import hashlib

def verify_signature(payload_bytes: bytes, secret: str, header_value: str) -> bool:
    expected = 'sha256=' + hmac.new(
        secret.encode(), payload_bytes, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, header_value)
```

**Node.js**

```javascript
const crypto = require('crypto');

function verifySignature(payloadBuffer, secret, headerValue) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(payloadBuffer)
    .digest('hex');
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(headerValue));
}
```

**Go**

```go
import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
)

func verifySignature(payload []byte, secret, headerValue string) bool {
    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write(payload)
    expected := "sha256=" + hex.EncodeToString(mac.Sum(nil))
    return hmac.Equal([]byte(expected), []byte(headerValue))
}
```

## Request Headers

Every webhook request includes the following headers:

| Header                 | Value                    | Description                                   |
| ---------------------- | ------------------------ | --------------------------------------------- |
| `Content-Type`         | `application/json`       | Payload format                                |
| `LinuxGuard-Signature` | `sha256=<hex>`           | HMAC-SHA256 signature of the raw request body |
| `LinuxGuard-Event`     | `signal_created`         | Event type                                    |
| `LinuxGuard-Delivery`  | UUID                     | Unique delivery identifier for deduplication  |
| `LinuxGuard-Timestamp` | Unix epoch               | Time the request was sent                     |
| `User-Agent`           | `LinuxGuard-Webhook/1.0` | Sender identification                         |

## Payload Reference

All webhook deliveries use the V1 payload envelope. The top-level fields wrap the signal data object.

**Top-level fields**

| Field         | Type   | Description                               |
| ------------- | ------ | ----------------------------------------- |
| `event_type`  | string | Always `signal_created` for signal alerts |
| `version`     | string | Payload version, currently `v1`           |
| `timestamp`   | string | ISO 8601 timestamp of the delivery        |
| `tenant_id`   | string | Your tenant identifier                    |
| `data`        | object | Signal data (see fields below)            |
| `console_url` | string | Link to the signal in the console         |

**Signal fields (nested under `data`)**

| Field           | Type    | Description                                    |
| --------------- | ------- | ---------------------------------------------- |
| `signal_id`     | string  | Unique signal identifier                       |
| `signal_type`   | string  | Signal type (e.g., `sudo_command_executed`)    |
| `severity`      | integer | Signal severity: 1 (info) to 5 (critical)      |
| `description`   | string  | Human-readable signal description              |
| `server_id`     | string  | Identifier of the reporting server             |
| `server_name`   | string  | Hostname of the reporting server               |
| `identity_id`   | string  | Identifier of the associated identity          |
| `identity_name` | string  | Username or service account name               |
| `environment`   | string  | Agent environment tag                          |
| `created_at`    | string  | ISO 8601 timestamp when the signal was created |

**Example payload**

```json
{
  "event_type": "signal_created",
  "version": "v1",
  "timestamp": "2026-03-02T14:32:01Z",
  "tenant_id": "<TENANT_ID>",
  "data": {
    "signal_id": "sig_abc123",
    "signal_type": "sudo_command_executed",
    "severity": 4,
    "description": "Sudo command executed",
    "server_id": "srv_xyz",
    "server_name": "web-01",
    "identity_id": "id_jsmith",
    "identity_name": "jsmith",
    "environment": "production",
    "created_at": "2026-03-02T14:31:58Z"
  },
  "console_url": "https://console.linuxguard.io/signals"
}
```

## Custom Headers

Each webhook endpoint can be configured with additional request headers that are sent with every delivery. Common uses include authentication tokens for the receiving system (for example, `Authorization: Bearer <TOKEN>`) and routing headers for your infrastructure.

To add a custom header, enter the header name and value in the **Custom Headers** section when creating or editing an endpoint.

***

**Related**: [Alerting & SIEM Integration](/explanation/explanation/alerting.md) | [Configure Notification Rules](/how-to-guides/how-to/configure-notification-rules.md) | [Syslog Forwarding](/how-to-guides/how-to/configure-notification-rules/syslog-forwarding.md) | [Splunk HEC Integration](/how-to-guides/how-to/configure-notification-rules/splunk-hec-integration.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.linuxguard.io/how-to-guides/how-to/configure-notification-rules/webhook-integration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
