@@ -52,6 +52,12 @@ def generate_slack_signature(payload, secret, timestamp)
52
52
"v0=#{ digest } "
53
53
end
54
54
55
+ def generate_tailscale_signature ( payload , secret , timestamp = unix_timestamp )
56
+ signing_payload = "#{ timestamp } .#{ payload } "
57
+ signature = OpenSSL ::HMAC . hexdigest ( OpenSSL ::Digest . new ( "sha256" ) , secret , signing_payload )
58
+ "t=#{ timestamp } ,v1=#{ signature } "
59
+ end
60
+
55
61
def current_timestamp
56
62
Time . now . utc . iso8601
57
63
end
@@ -520,5 +526,47 @@ def expired_unix_timestamp(seconds_ago = 600)
520
526
expect ( response . code ) . to eq ( "500" )
521
527
end
522
528
end
529
+
530
+ describe "tailscale" do
531
+ it "successfully processes a valid POST request from a tailscale style webhook" do
532
+ payload = { event : "user.login" , user : { id : "12345" } }
533
+ json_payload = payload . to_json
534
+ timestamp = unix_timestamp
535
+ signature = generate_tailscale_signature ( json_payload , FAKE_ALT_HMAC_SECRET , timestamp )
536
+ headers = json_headers ( "Tailscale-Webhook-Signature" => signature )
537
+ response = make_request ( :post , "/webhooks/tailscale" , json_payload , headers )
538
+ expect_response ( response , Net ::HTTPSuccess )
539
+
540
+ body = parse_json_response ( response )
541
+ expect ( body [ "status" ] ) . to eq ( "success" )
542
+ end
543
+
544
+ it "rejects request with invalid signature" do
545
+ payload = { event : "user.login" , user : { id : "12345" } }
546
+ json_payload = payload . to_json
547
+ headers = json_headers ( "Tailscale-Webhook-Signature" => "t=1663781880,v1=invalidsignature" )
548
+ response = make_request ( :post , "/webhooks/tailscale" , json_payload , headers )
549
+ expect_response ( response , Net ::HTTPUnauthorized , "authentication failed" )
550
+ end
551
+
552
+ it "rejects request with missing signature header" do
553
+ payload = { event : "user.login" , user : { id : "12345" } }
554
+ json_payload = payload . to_json
555
+ response = make_request ( :post , "/webhooks/tailscale" , json_payload , json_headers )
556
+ expect_response ( response , Net ::HTTPUnauthorized , "authentication failed" )
557
+ end
558
+
559
+ it "rejects request with wrong signature algorithm" do
560
+ payload = { event : "user.login" , user : { id : "12345" } }
561
+ json_payload = payload . to_json
562
+ timestamp = unix_timestamp
563
+ # Generate with sha1 instead of sha256
564
+ signing_payload = "#{ timestamp } .#{ json_payload } "
565
+ wrong_signature = OpenSSL ::HMAC . hexdigest ( OpenSSL ::Digest . new ( "sha1" ) , FAKE_ALT_HMAC_SECRET , signing_payload )
566
+ headers = json_headers ( "Tailscale-Webhook-Signature" => "t=#{ timestamp } ,v1=#{ wrong_signature } " )
567
+ response = make_request ( :post , "/webhooks/tailscale" , json_payload , headers )
568
+ expect_response ( response , Net ::HTTPUnauthorized , "authentication failed" )
569
+ end
570
+ end
523
571
end
524
572
end
0 commit comments