mirror of https://github.com/h44z/wg-portal.git
				
				
				
			
		
			
				
	
	
		
			285 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Markdown
		
	
	
	
			
		
		
	
	
			285 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Markdown
		
	
	
	
| 
 | |
| Webhooks allow WireGuard Portal to notify external services about events such as user creation, device changes, or configuration updates. This enables integration with other systems and automation workflows.
 | |
| 
 | |
| When webhooks are configured and a specified event occurs, WireGuard Portal sends an HTTP **POST** request to the configured webhook URL. 
 | |
| The payload contains event-specific data in JSON format.
 | |
| 
 | |
| ## Configuration
 | |
| 
 | |
| All available configuration options for webhooks can be found in the [configuration overview](../configuration/overview.md#webhook).
 | |
| 
 | |
| A basic webhook configuration looks like this:
 | |
| 
 | |
| ```yaml
 | |
| webhook:
 | |
|   url: https://your-service.example.com/webhook
 | |
| ```
 | |
| 
 | |
| ### Security
 | |
| 
 | |
| Webhooks can be secured by using a shared secret. This secret is included in the `Authorization` header of the webhook request, allowing your service to verify the authenticity of the request.
 | |
| You can set the shared secret in the webhook configuration:
 | |
| 
 | |
| ```yaml
 | |
| webhook:
 | |
|   url: https://your-service.example.com/webhook
 | |
|   secret: "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
 | |
| ```
 | |
| 
 | |
| You should also make sure that your webhook endpoint is secured with HTTPS to prevent eavesdropping and tampering.
 | |
| 
 | |
| ## Available Events
 | |
| 
 | |
| WireGuard Portal supports various events that can trigger webhooks. The following events are available:
 | |
| 
 | |
| - `create`: Triggered when a new entity is created.
 | |
| - `update`: Triggered when an existing entity is updated.
 | |
| - `delete`: Triggered when an entity is deleted.
 | |
| - `connect`: Triggered when a user connects to the VPN.
 | |
| - `disconnect`: Triggered when a user disconnects from the VPN.
 | |
| 
 | |
| The following entity models are supported for webhook events:
 | |
| 
 | |
| - `user`: WireGuard Portal users support creation, update, or deletion events.
 | |
| - `peer`: Peers support creation, update, or deletion events. Via the `peer_metric` entity, you can also receive connection status updates.
 | |
| - `peer_metric`: Peer metrics support connection status updates, such as when a peer connects or disconnects.
 | |
| - `interface`: WireGuard interfaces support creation, update, or deletion events.
 | |
| 
 | |
| ## Payload Structure
 | |
| 
 | |
| All webhook events send a JSON payload containing relevant data. The structure of the payload depends on the event type and entity involved.
 | |
| A common shell structure for webhook payloads is as follows:
 | |
| 
 | |
| ```json
 | |
| {
 | |
|   "event": "create", // The event type, e.g. "create", "update", "delete", "connect", "disconnect"
 | |
|   "entity": "user",  // The entity type, e.g. "user", "peer", "peer_metric", "interface"
 | |
|   "identifier": "the-user-identifier", // Unique identifier of the entity, e.g. user ID or peer ID
 | |
|   "payload": {
 | |
|     // The payload of the event, e.g. a Peer model.
 | |
|     // Detailed model descriptions are provided below.
 | |
|   }
 | |
| }
 | |
| ```
 | |
| 
 | |
| ### Payload Models
 | |
| 
 | |
| All payload models are encoded as JSON objects. Fields with empty values might be omitted in the payload.
 | |
| 
 | |
| #### User Payload (entity: `user`)
 | |
| 
 | |
| | JSON Field     | Type        | Description                       |
 | |
| |----------------|-------------|-----------------------------------|
 | |
| | CreatedBy      | string      | Creator identifier                |
 | |
| | UpdatedBy      | string      | Last updater identifier           |
 | |
| | CreatedAt      | time.Time   | Time of creation                  |
 | |
| | UpdatedAt      | time.Time   | Time of last update               |
 | |
| | Identifier     | string      | Unique user identifier            |
 | |
| | Email          | string      | User email                        |
 | |
| | Source         | string      | Authentication source             |
 | |
| | ProviderName   | string      | Name of auth provider             |
 | |
| | IsAdmin        | bool        | Whether user has admin privileges |
 | |
| | Firstname      | string      | User's first name (optional)      |
 | |
| | Lastname       | string      | User's last name (optional)       |
 | |
| | Phone          | string      | Contact phone number (optional)   |
 | |
| | Department     | string      | User's department (optional)      |
 | |
| | Notes          | string      | Additional notes (optional)       |
 | |
| | Disabled       | *time.Time  | When user was disabled            |
 | |
| | DisabledReason | string      | Reason for deactivation           |
 | |
| | Locked         | *time.Time  | When user account was locked      |
 | |
| | LockedReason   | string      | Reason for being locked           |
 | |
| 
 | |
| 
 | |
| #### Peer Payload (entity: `peer`)
 | |
| 
 | |
| | JSON Field           | Type       | Description                            |
 | |
| |----------------------|------------|----------------------------------------|
 | |
| | CreatedBy            | string     | Creator identifier                     |
 | |
| | UpdatedBy            | string     | Last updater identifier                |
 | |
| | CreatedAt            | time.Time  | Creation timestamp                     |
 | |
| | UpdatedAt            | time.Time  | Last update timestamp                  |
 | |
| | Endpoint             | string     | Peer endpoint address                  |
 | |
| | EndpointPublicKey    | string     | Public key of peer endpoint            |
 | |
| | AllowedIPsStr        | string     | Allowed IPs                            |
 | |
| | ExtraAllowedIPsStr   | string     | Extra allowed IPs                      |
 | |
| | PresharedKey         | string     | Pre-shared key for encryption          |
 | |
| | PersistentKeepalive  | int        | Keepalive interval in seconds          |
 | |
| | DisplayName          | string     | Display name of the peer               |
 | |
| | Identifier           | string     | Unique identifier                      |
 | |
| | UserIdentifier       | string     | Associated user ID (optional)          |
 | |
| | InterfaceIdentifier  | string     | Interface this peer is attached to     |
 | |
| | Disabled             | *time.Time | When the peer was disabled             |
 | |
| | DisabledReason       | string     | Reason for being disabled              |
 | |
| | ExpiresAt            | *time.Time | Expiration date                        |
 | |
| | Notes                | string     | Notes for this peer                    |
 | |
| | AutomaticallyCreated | bool       | Whether peer was auto-generated        |
 | |
| | PrivateKey           | string     | Peer private key                       |
 | |
| | PublicKey            | string     | Peer public key                        |
 | |
| | InterfaceType        | string     | Type of the peer interface             |
 | |
| | Addresses            | []string   | IP addresses                           |
 | |
| | CheckAliveAddress    | string     | Address used for alive checks          |
 | |
| | DnsStr               | string     | DNS servers                            |
 | |
| | DnsSearchStr         | string     | DNS search domains                     |
 | |
| | Mtu                  | int        | MTU (Maximum Transmission Unit)        |
 | |
| | FirewallMark         | uint32     | Firewall mark (optional)               |
 | |
| | RoutingTable         | string     | Custom routing table (optional)        |
 | |
| | PreUp                | string     | Command before bringing up interface   |
 | |
| | PostUp               | string     | Command after bringing up interface    |
 | |
| | PreDown              | string     | Command before bringing down interface |
 | |
| | PostDown             | string     | Command after bringing down interface  |
 | |
| 
 | |
| 
 | |
| #### Interface Payload (entity: `interface`)
 | |
| 
 | |
| | JSON Field                 | Type       | Description                            |
 | |
| |----------------------------|------------|----------------------------------------|
 | |
| | CreatedBy                  | string     | Creator identifier                     |
 | |
| | UpdatedBy                  | string     | Last updater identifier                |
 | |
| | CreatedAt                  | time.Time  | Creation timestamp                     |
 | |
| | UpdatedAt                  | time.Time  | Last update timestamp                  |
 | |
| | Identifier                 | string     | Unique identifier                      |
 | |
| | PrivateKey                 | string     | Private key for the interface          |
 | |
| | PublicKey                  | string     | Public key for the interface           |
 | |
| | ListenPort                 | int        | Listening port                         |
 | |
| | Addresses                  | []string   | IP addresses                           |
 | |
| | DnsStr                     | string     | DNS servers                            |
 | |
| | DnsSearchStr               | string     | DNS search domains                     |
 | |
| | Mtu                        | int        | MTU (Maximum Transmission Unit)        |
 | |
| | FirewallMark               | uint32     | Firewall mark                          |
 | |
| | RoutingTable               | string     | Custom routing table                   |
 | |
| | PreUp                      | string     | Command before bringing up interface   |
 | |
| | PostUp                     | string     | Command after bringing up interface    |
 | |
| | PreDown                    | string     | Command before bringing down interface |
 | |
| | PostDown                   | string     | Command after bringing down interface  |
 | |
| | SaveConfig                 | bool       | Whether to save config to file         |
 | |
| | DisplayName                | string     | Human-readable name                    |
 | |
| | Type                       | string     | Type of interface                      |
 | |
| | DriverType                 | string     | Driver used                            |
 | |
| | Disabled                   | *time.Time | When the interface was disabled        |
 | |
| | DisabledReason             | string     | Reason for being disabled              |
 | |
| | PeerDefNetworkStr          | string     | Default peer network configuration     |
 | |
| | PeerDefDnsStr              | string     | Default peer DNS servers               |
 | |
| | PeerDefDnsSearchStr        | string     | Default peer DNS search domains        |
 | |
| | PeerDefEndpoint            | string     | Default peer endpoint                  |
 | |
| | PeerDefAllowedIPsStr       | string     | Default peer allowed IPs               |
 | |
| | PeerDefMtu                 | int        | Default peer MTU                       |
 | |
| | PeerDefPersistentKeepalive | int        | Default keepalive value                |
 | |
| | PeerDefFirewallMark        | uint32     | Default firewall mark for peers        |
 | |
| | PeerDefRoutingTable        | string     | Default routing table for peers        |
 | |
| | PeerDefPreUp               | string     | Default peer pre-up command            |
 | |
| | PeerDefPostUp              | string     | Default peer post-up command           |
 | |
| | PeerDefPreDown             | string     | Default peer pre-down command          |
 | |
| | PeerDefPostDown            | string     | Default peer post-down command         |
 | |
| 
 | |
| 
 | |
| #### Peer Metrics Payload (entity: `peer_metric`)
 | |
| 
 | |
| | JSON Field | Type       | Description                |
 | |
| |------------|------------|----------------------------|
 | |
| | Status     | PeerStatus | Current status of the peer |
 | |
| | Peer       | Peer       | Peer  data                 |
 | |
| 
 | |
| `PeerStatus` sub-structure:
 | |
| 
 | |
| | JSON Field       | Type       | Description                  |
 | |
| |------------------|------------|------------------------------|
 | |
| | UpdatedAt        | time.Time  | Time of last status update   |
 | |
| | IsConnected      | bool       | Is peer currently connected  |
 | |
| | IsPingable       | bool       | Can peer be pinged           |
 | |
| | LastPing         | *time.Time | Time of last successful ping |
 | |
| | BytesReceived    | uint64     | Bytes received from peer     |
 | |
| | BytesTransmitted | uint64     | Bytes sent to peer           |
 | |
| | Endpoint         | string     | Last known endpoint          |
 | |
| | LastHandshake    | *time.Time | Last successful handshake    |
 | |
| | LastSessionStart | *time.Time | Time the last session began  |
 | |
| 
 | |
| 
 | |
| ### Example Payloads
 | |
| 
 | |
| The following payload is an example of a webhook event when a peer connects to the VPN:
 | |
| 
 | |
| ```json
 | |
| {
 | |
|   "event": "connect",
 | |
|   "entity": "peer_metric",
 | |
|   "identifier": "Fb5TaziAs1WrPBjC/MFbWsIelVXvi0hDKZ3YQM9wmU8=",
 | |
|   "payload": {
 | |
|     "Status": {
 | |
|       "UpdatedAt": "2025-06-27T22:20:08.734900034+02:00",
 | |
|       "IsConnected": true,
 | |
|       "IsPingable": false,
 | |
|       "BytesReceived": 212,
 | |
|       "BytesTransmitted": 2884,
 | |
|       "Endpoint": "10.55.66.77:58756",
 | |
|       "LastHandshake": "2025-06-27T22:19:46.580842776+02:00",
 | |
|       "LastSessionStart": "2025-06-27T22:19:46.580842776+02:00"
 | |
|     },
 | |
|     "Peer": {
 | |
|       "CreatedBy": "admin@wgportal.local",
 | |
|       "UpdatedBy": "admin@wgportal.local",
 | |
|       "CreatedAt": "2025-06-26T21:43:49.251839574+02:00",
 | |
|       "UpdatedAt": "2025-06-27T22:18:39.67763985+02:00",
 | |
|       "Endpoint": "10.55.66.1:51820",
 | |
|       "EndpointPublicKey": "eiVibpi3C2PUPcx2kwA5s09OgHx7AEaKMd33k0LQ5mM=",
 | |
|       "AllowedIPsStr": "10.11.12.0/24,fdfd:d3ad:c0de:1234::/64",
 | |
|       "ExtraAllowedIPsStr": "",
 | |
|       "PresharedKey": "p9DDeLUSLOdQcjS8ZsBAiqUzwDIUvTyzavRZFuzhvyE=",
 | |
|       "PersistentKeepalive": 16,
 | |
|       "DisplayName": "Peer Fb5TaziA",
 | |
|       "Identifier": "Fb5TaziAs1WrPBjC/MFbWsIelVXvi0hDKZ3YQM9wmU8=",
 | |
|       "UserIdentifier": "admin@wgportal.local",
 | |
|       "InterfaceIdentifier": "wgTesting",
 | |
|       "AutomaticallyCreated": false,
 | |
|       "PrivateKey": "QBFNBe+7J49ergH0ze2TGUJMFrL/2bOL50Z2cgluYW8=",
 | |
|       "PublicKey": "Fb5TaziAs1WrPBjC/MFbWsIelVXvi0hDKZ3YQM9wmU8=",
 | |
|       "InterfaceType": "client",
 | |
|       "Addresses": [
 | |
|         "10.11.12.10/32",
 | |
|         "fdfd:d3ad:c0de:1234::a/128"
 | |
|       ],
 | |
|       "CheckAliveAddress": "",
 | |
|       "DnsStr": "",
 | |
|       "DnsSearchStr": "",
 | |
|       "Mtu": 1420
 | |
|     }
 | |
|   }
 | |
| }
 | |
| ```
 | |
| 
 | |
| Here is another example of a webhook event when a peer is updated:
 | |
| 
 | |
| ```json
 | |
| {
 | |
|   "event": "update",
 | |
|   "entity": "peer",
 | |
|   "identifier": "Fb5TaziAs1WrPBjC/MFbWsIelVXvi0hDKZ3YQM9wmU8=",
 | |
|   "payload": {
 | |
|     "CreatedBy": "admin@wgportal.local",
 | |
|     "UpdatedBy": "admin@wgportal.local",
 | |
|     "CreatedAt": "2025-06-26T21:43:49.251839574+02:00",
 | |
|     "UpdatedAt": "2025-06-27T22:18:39.67763985+02:00",
 | |
|     "Endpoint": "10.55.66.1:51820",
 | |
|     "EndpointPublicKey": "eiVibpi3C2PUPcx2kwA5s09OgHx7AEaKMd33k0LQ5mM=",
 | |
|     "AllowedIPsStr": "10.11.12.0/24,fdfd:d3ad:c0de:1234::/64",
 | |
|     "ExtraAllowedIPsStr": "",
 | |
|     "PresharedKey": "p9DDeLUSLOdQcjS8ZsBAiqUzwDIUvTyzavRZFuzhvyE=",
 | |
|     "PersistentKeepalive": 16,
 | |
|     "DisplayName": "Peer Fb5TaziA",
 | |
|     "Identifier": "Fb5TaziAs1WrPBjC/MFbWsIelVXvi0hDKZ3YQM9wmU8=",
 | |
|     "UserIdentifier": "admin@wgportal.local",
 | |
|     "InterfaceIdentifier": "wgTesting",
 | |
|     "AutomaticallyCreated": false,
 | |
|     "PrivateKey": "QBFNBe+7J49ergH0ze2TGUJMFrL/2bOL50Z2cgluYW8=",
 | |
|     "PublicKey": "Fb5TaziAs1WrPBjC/MFbWsIelVXvi0hDKZ3YQM9wmU8=",
 | |
|     "InterfaceType": "client",
 | |
|     "Addresses": [
 | |
|       "10.11.12.10/32",
 | |
|       "fdfd:d3ad:c0de:1234::a/128"
 | |
|     ],
 | |
|     "CheckAliveAddress": "",
 | |
|     "DnsStr": "",
 | |
|     "DnsSearchStr": "",
 | |
|     "Mtu": 1420
 | |
|   }
 | |
| }
 | |
| ``` |