Webhooks
Webhooks allow you to monitor and respond to events within your Buildkite organization, providing a real time view of activity and allowing you to extend and integrate Buildkite into your systems.
Webhooks can be added and configured on your organization's Notification Services settings page.
Events
You can subscribe to one or more of the following events:
Event | Description |
---|---|
ping |
Webhook notification settings have changed |
build.scheduled |
A build has been scheduled |
build.running |
A build has started running |
build.failing |
A build is failing |
build.finished |
A build has finished |
job.scheduled |
A job has been scheduled |
job.started |
A command step job has started running on an agent |
job.finished |
A job has finished |
job.activated |
A block step job has been unblocked using the web or API |
agent.connected |
An agent has connected to the API |
agent.lost |
An agent has been marked as lost. This happens when Buildkite stops receiving pings from the agent |
agent.disconnected |
An agent has disconnected. This happens when the agent shuts down and disconnects from the API |
agent.stopping |
An agent is stopping. This happens when an agent is instructed to stop from the API. It first transitions to stopping and finishes any current jobs |
agent.stopped |
An agent has stopped. This happens when an agent is instructed to stop from the API. It can be graceful or forceful |
agent.blocked |
An agent has been blocked. This happens when an agent's IP address is no longer included in the agent token's allowed IP addresses |
cluster_token.registration_blocked |
An attempted agent registration has been blocked because the request IP address is not included in the agent token's allowed IP addresses |
HTTP headers
The following HTTP headers are present in every webhook request, which allow you to identify the event that took place, and to verify the authenticity of the request:
X-Buildkite-Event |
The type of event Example: |
---|
One of either the Token or Signature headers will be present in every webhook request. The token value and header setting can be found under Token in your Webhook Notification service.
Your selection in the Webhook Notification service will determine which is sent:
X-Buildkite-Token |
The webhook's token. Example: |
---|---|
X-Buildkite-Signature |
The signature created from your webhook payload, webhook token, and the SHA-256 hash function. Example: |
HTTP request body
Each event's data is sent JSON encoded in the request body. See each event's documentation (agent, build, job, ping) to see which keys are available in the payload. For example:
{
"event": "build.started",
"build": {
"keys": "vals"
},
"sender": {
"keys": "vals"
}
}
Note that if a build transitions between states very quickly, for example from blocked (finished
) to unblocked (running
), the webhook may be in a different state from the actual build. This is a known limitation of webhooks, in that they may represent a later version of the object than the one that triggered the event.
Webhook token
By default, Buildkite will send a token with each webhook in the X-Buildkite-Token
header.
The token value and header setting can be found under Token in your Webhook Notification service.
The token is passed in clear text.
Webhook signature
Buildkite can optionally send an HMAC signature in place of a webhook token.
The X-Buildkite-Signature
header contains a timestamp and an HMAC signature. The timestamp is prefixed by timestamp=
and the signature is prefixed by signature=
.
Buildkite generates the signature using HMAC-SHA256; a hash-based message authentication code HMAC used with the SHA-256 hash function and a secret key. The webhook token value is used as the secret key. The timestamp is an integer representation of a UTC timestamp. The raw request body is the signed message.
The token value and header setting can be found under Token in your Webhook Notification service.
Verifying HMAC signatures
When using HMAC signatures, you'll want to verify that the signature is legitimate.
Using the token as the secret along with the timestamp from the webhook, compute the expected signature based on the raw request body. There should be a library available in the programming language you are using that can perform this operation.
Compare the code to the signature received in the webhook. If they do not match, your payload has been altered.
The below example in Ruby verifies the signature and timestamp using the OpenSSL gem's HMAC :
require 'openssl'
class BuildkiteWebhook
def self.valid?(webhook_request_body, header, secret)
timestamp, signature = get_timestamp_and_signatures(header)
expected = OpenSSL::HMAC.hexdigest("sha256", secret, "#{timestamp}.#{webhook_request_body}")
Rack::Utils.secure_compare(expected, signature)
end
def self.get_timestamp_and_signatures(header)
parts = header.split(",").map { |kv| kv.split("=", 2).map(&:strip) }.to_h
[parts["timestamp"], parts["signature"]]
end
end
BuildkiteWebhook.valid?(
request.body.read,
request.headers["X-Buildkite-Signature"],
ENV["BUILDKITE_WEBHOOK_SECRET"]
)
Defending against replay attacks
A replay attack is when an attacker intercepts a valid payload and its signature, then re-transmits them. One way to help mitigate such attacks is to send a timestamp with your payload and only accept them within a short window (for example, 5 minutes).
Buildkite sends a timestamp in the X-Buildkite-Signature
header. The timestamp is part of the signed payload so that it is verified by the signature. An attacker will not be able to change the timestamp without invalidating the signature.
To help protect against a replay attack, upon receipt of a webhook:
- Verify the signature
- Check the timestamp against the current time
If the webhook's timestamp is within your chosen window of the current time, it can reasonably be assumed to be the original webhook.
Example implementations
The following example repositories show how to receive a webhook event and trigger a LIFX powered build light. You can browse their source, fork them, and deploy them to Heroku directly from their GitHub readmes, or use them as an example to implement webhooks in your tool of choice.
Node webhook example application github.com/buildkite/lifx-buildkite-build-light-node
Ruby webhook example application github.com/buildkite/lifx-buildkite-build-light-ruby
PHP webhook example application github.com/buildkite/lifx-buildkite-build-light-php
Webtask.io webhook example application github.com/buildkite/lifx-buildkite-build-light-webtask
Request logs
The last 20 webhook request and responses are saved, so you can debug and inspect your webhook. Each webhook's request logs are available on the bottom of their settings page.