@@ -52,6 +52,12 @@ def generate_slack_signature(payload, secret, timestamp)
5252 "v0=#{ digest } "
5353 end
5454
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+
5561 def current_timestamp
5662 Time . now . utc . iso8601
5763 end
@@ -520,5 +526,47 @@ def expired_unix_timestamp(seconds_ago = 600)
520526 expect ( response . code ) . to eq ( "500" )
521527 end
522528 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
523571 end
524572end
0 commit comments