Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2aae6af
Initial plan
Copilot Nov 1, 2025
0267dcb
Add webhook signature verification support
Copilot Nov 1, 2025
a644d21
Add API test for HTTP shovel signature configuration
Copilot Nov 1, 2025
f4d5a40
Add documentation for webhook signature secret parameter
Copilot Nov 1, 2025
7a38f6c
Add webhook signature verification documentation with examples
Copilot Nov 1, 2025
b30822d
Optimize body handling to only read into memory when signature is needed
Copilot Nov 1, 2025
cb50a85
Use Standard Webhooks format for webhook signatures
baelter Dec 10, 2025
f156d51
Replace verbose webhook docs with brief README note
baelter Dec 10, 2025
f112483
Use RoughTime for signature timestamp
baelter Dec 11, 2025
e967eae
Add max_signed_webhook_payload config to limit memory usage
baelter Dec 11, 2025
79f33c6
Fix merge mistake
baelter Dec 11, 2025
6785b26
Remove redundant spec
baelter Dec 11, 2025
e2663dd
Refactor: DRY up HTTP webhook server setup in shovel specs
baelter Dec 11, 2025
37bc8dc
lint
baelter Dec 11, 2025
d322f3d
Right level of dryness
baelter Dec 11, 2025
32dd8f5
Fix nested it block in shovel_spec.cr
baelter Dec 11, 2025
cbae353
Treat empty signature secret as no secret configured
baelter Dec 11, 2025
aeaddf6
Support signature key rotation per Standard Webhooks spec
baelter Dec 11, 2025
28a2b2c
Update OpenAPI docs for Standard Webhooks signature
baelter Dec 11, 2025
aa7dffa
Add UI support for webhook signature secret
baelter Dec 11, 2025
b55d3db
Add --dest-signature-secret option to lavinmqctl add_shovel
baelter Dec 11, 2025
ec4a81e
Make secret masking generic for all parameters
baelter Dec 11, 2025
fb4d829
Add Standard Webhooks support to changelog
baelter Dec 11, 2025
f99fbaa
Default max_signed_webhook_payload to frame_max (128KB)
baelter Dec 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added
- Standard Webhooks signature support for HTTP shovels [#1423](https://github.com/cloudamqp/lavinmq/pull/1423)

## [2.6.0] - 2025-12-05

This release introduces Geographic Information System (GIS) filtering for streams, enhanced performance testing capabilities, as well as many other improvements and bugfixes.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ Use [lavinmqperf](https://lavinmq.com/documentation/lavinmqperf) to benchmark yo
- Automatic leader election in clusters via etcd

### Other Functionality
- Shovels
- Shovels (including HTTP shovels with [Standard Webhooks](https://www.standardwebhooks.com/) signature support)
- Queue & Exchange federation
- Single active consumer
- Stream queues
Expand Down
57 changes: 57 additions & 0 deletions spec/api/shovels_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,61 @@ describe LavinMQ::HTTP::ShovelsController do
end
end
end

describe "GET api/parameters/shovel" do
it "should mask dest-signature-secret in response" do
with_http_server do |http, s|
# Create a shovel parameter with a signature secret via API
body = {
value: {
"src-uri": s.amqp_url,
"dest-uri": "https://example.com/webhook",
"src-queue": "test-q",
"dest-signature-secret": "my-secret-key",
},
}
response = http.put("/api/parameters/shovel/%2F/secret-shovel", body: body.to_json)
response.status_code.should eq 201

# Fetch and verify secret is masked
response = http.get("/api/parameters/shovel/%2F/secret-shovel")
response.status_code.should eq 200
json = JSON.parse(response.body)
json["value"]["dest-signature-secret"].as_s.should eq "********"
end
end

it "should preserve dest-signature-secret when updating without providing it" do
with_http_server do |http, s|
# Create a shovel parameter with a signature secret
body = {
value: {
"src-uri": s.amqp_url,
"dest-uri": "https://example.com/webhook",
"src-queue": "test-q",
"dest-signature-secret": "my-secret-key",
},
}
response = http.put("/api/parameters/shovel/%2F/preserve-secret-shovel", body: body.to_json)
response.status_code.should eq 201

# Update without providing the secret
body = {
value: {
"src-uri": s.amqp_url,
"dest-uri": "https://example.com/webhook",
"src-queue": "updated-q",
},
}
response = http.put("/api/parameters/shovel/%2F/preserve-secret-shovel", body: body.to_json)
response.status_code.should eq 204

# Verify secret is still there (masked)
response = http.get("/api/parameters/shovel/%2F/preserve-secret-shovel")
json = JSON.parse(response.body)
json["value"]["dest-signature-secret"].as_s.should eq "********"
json["value"]["src-queue"].as_s.should eq "updated-q"
end
end
end
end
Loading
Loading