General-purpose webhook URLs
A general-purpose webhook URL can be configured for the Destinations of organization and application Notifications and Important Alerts.
Notifications pings to a webhook URL can be useful for:
- Pinging a testing service whenever a particular environment is updated. This can include page speed tests or integration testing to ensure that a checkout process is still working as expected.
- Logging the deployment against a datastore (e.g. a Google spreadsheet).
Request header and versions
The webhook request is sent with an x-wpvip-webhook
HTTP request header. The x-wpvip-webhook
header value is a string indicating the version number of the webhook payload.
When breaking changes are made to the payload structure the version number will be incremented.
- Current webhook version:
v1
(e.g.x-wpvip-webhook: "v1"
) - Legacy webhook version:
v0
(e.g.x-wpvip-webhook: "v0"
)
Request body
The service receiving the Notifications ping must be able to accept an HTTP POST
. The ping sent by Notifications is a JSON-formatted request body.
Example request body structure for an event related to a single environment:
{
"type": "environment:code:deployed",
"timestamp": "2024-01-26T22:16:30.000Z",
"data": {
"application": {
"id": 8886,
"name": "example-app"
},
"branch": "develop",
"commit": {
"author": "example-user",
"description": "Example commit message",
"hash": "0abc1234e5af99deadbeefb98765432181e03b1a5b5d69"
},
"deploymentId": 12345678,
"environment": {
"domain": "develop.example.com",
"id": 5678,
"type": "develop"
},
"repo": "wpcomvip/example-app"
}
}
Example request body structure for an event related to more than one environment:
{
"data": {
"environments": [
{
"appId": 8886,
"appName": "example-app",
"envName": "production"
},
{
"appId": 8886,
"appName": "example-app",
"envName": "staging"
}
],
"organization": {
"id": 123,
"name": "My Org"
},
"severity": "CRITICAL",
"severityScore": "7.4",
"vulnerabilityId": "abc6def4-abab-4545-9bd0-2222eeeecccc",
"vulnerabilityTitle": "ExamplePlugin < 1.2.7 - Authenticated(Contributor+) Stored Cross-Site Scripting via Shortcode"
},
"timestamp": "2024-07-11T18:59:48.000Z",
"type": "organization:code:vulnerability-found"
}
Note
Very infrequently, an environment might have a name
value assigned to it in addition to a type
(e.g. “develop.01” where “develop” is the type
value and “01” is the name
value). For these environments, both the type
and the name
keys and values will be included in the payload.
Event types
The type
payload property contains a string that indicates the kind of event that occurred. The behavior of the request handler can vary depending on the event type.
Currently supported event types:
environment:code:deployed
environment:code:deploy-failed
environment:code:vulnerability-found
organization:code:vulnerability-found
Request verification
Outbound webhook Notifications sent to endpoints configured by customers can be identified by the VIP User-Agent VIP Webhooks (+https://docs.wpvip.com/vip-user-agents)
. The presence of this User-Agent is a useful reference for identifying the source of a request, but it should not be considered authoritative proof. Customers can optionally configure more reliable verification methods for the source of Notifications that are sent to webhook URLs.
Shared secret
When configuring a webhook URL for a Destination, a unique parameter string can be added to the URL for verification purposes. The unique parameter string can then be used as a “shared secret” by code on the receiving end to verify that the webhook came from WordPress VIP.
A unique parameter string can be generated in many ways, but openssl
is a useful library for generating unique, high-entropy strings for shared secrets.
In a webhook handler on the receiving end, a timing-safe comparison can be used to verify that the secret
parameter that was sent in the webhook matches the expected value.
This example demonstrates a version of this type of verification in PHP:
- Generate a string to be used as a shared secret with the command:
openssl rand -hex 24
- Copy the output and add it to a webhook URL as the value of a
?secret
query parameter. For example:
https://example.com/webhooks/wpvip?secret=a18b504dcc1a8ff2e476d93829f33
- Create an environment variable with VIP-CLI and set the shared secret string as its value. For this example, the environment variable is created with the name
WEBHOOK_SECRET
. - In a webhook handler on the receiving end, use a timing-safe comparison to verify that the
secret
parameter that was sent in the webhook matches the expected value of the environment variable.
<?php
...
$passed_secret = $_GET['secret'] ?? null;
if ( ! hash_equals( $passed_secret, WEBHOOK_SECRET ) ) {
wp_die( 'Invalid webhook' );
}
// Secret verified, handle webhook
...
IP address
WordPress VIP can also be verified as the sender of a webhook by IP address. Webhooks sent from WordPress VIP will always come from an IP address that belongs to the WordPress VIP Platform IP ranges.
Last updated: August 06, 2024