Webhook-to-SSE gateway with hierarchical topic routing and signature verification
at main 120 lines 3.2 kB view raw
1package main 2 3import ( 4 "crypto/hmac" 5 "crypto/sha1" 6 "crypto/sha256" 7 "encoding/hex" 8 "net/http" 9 "testing" 10) 11 12func computeHMACSHA256(secret, body string) string { 13 mac := hmac.New(sha256.New, []byte(secret)) 14 mac.Write([]byte(body)) 15 return "sha256=" + hex.EncodeToString(mac.Sum(nil)) 16} 17 18func computeHMACSHA1(secret, body string) string { 19 mac := hmac.New(sha1.New, []byte(secret)) 20 mac.Write([]byte(body)) 21 return "sha1=" + hex.EncodeToString(mac.Sum(nil)) 22} 23 24func TestNewVerifier_hmacSHA256(t *testing.T) { 25 v, err := NewVerifier("hmac-sha256") 26 if err != nil { 27 t.Fatalf("unexpected error: %v", err) 28 } 29 if v == nil { 30 t.Fatal("expected verifier, got nil") 31 } 32} 33 34func TestNewVerifier_hmacSHA1(t *testing.T) { 35 v, err := NewVerifier("hmac-sha1") 36 if err != nil { 37 t.Fatalf("unexpected error: %v", err) 38 } 39 if v == nil { 40 t.Fatal("expected verifier, got nil") 41 } 42} 43 44func TestNewVerifier_unknown(t *testing.T) { 45 _, err := NewVerifier("unknown-method") 46 if err == nil { 47 t.Fatal("expected error for unknown method") 48 } 49} 50 51func TestHMACSHA256_validSignature(t *testing.T) { 52 secret := "test-secret" 53 body := `{"action":"push"}` 54 sig := computeHMACSHA256(secret, body) 55 56 v, _ := NewVerifier("hmac-sha256") 57 headers := http.Header{"X-Hub-Signature-256": {sig}} 58 err := v.Verify([]byte(body), headers, secret, "X-Hub-Signature-256") 59 if err != nil { 60 t.Fatalf("expected valid signature, got error: %v", err) 61 } 62} 63 64func TestHMACSHA256_invalidSignature(t *testing.T) { 65 v, _ := NewVerifier("hmac-sha256") 66 headers := http.Header{"X-Hub-Signature-256": {"sha256=deadbeef"}} 67 err := v.Verify([]byte("body"), headers, "secret", "X-Hub-Signature-256") 68 if err == nil { 69 t.Fatal("expected error for invalid signature") 70 } 71} 72 73func TestHMACSHA256_missingHeader(t *testing.T) { 74 v, _ := NewVerifier("hmac-sha256") 75 headers := http.Header{} 76 err := v.Verify([]byte("body"), headers, "secret", "X-Hub-Signature-256") 77 if err == nil { 78 t.Fatal("expected error for missing signature header") 79 } 80} 81 82func TestHMACSHA1_validSignature(t *testing.T) { 83 secret := "test-secret" 84 body := `{"action":"push"}` 85 sig := computeHMACSHA1(secret, body) 86 87 v, _ := NewVerifier("hmac-sha1") 88 headers := http.Header{"X-Hub-Signature": {sig}} 89 err := v.Verify([]byte(body), headers, secret, "X-Hub-Signature") 90 if err != nil { 91 t.Fatalf("expected valid signature, got error: %v", err) 92 } 93} 94 95func TestHMACSHA256_wrongPrefix(t *testing.T) { 96 v, _ := NewVerifier("hmac-sha256") 97 headers := http.Header{"X-Hub-Signature-256": {"sha1=abc123"}} 98 err := v.Verify([]byte("body"), headers, "secret", "X-Hub-Signature-256") 99 if err == nil { 100 t.Fatal("expected error for wrong prefix") 101 } 102} 103 104func TestHMACSHA256_invalidHex(t *testing.T) { 105 v, _ := NewVerifier("hmac-sha256") 106 headers := http.Header{"X-Hub-Signature-256": {"sha256=not-hex!"}} 107 err := v.Verify([]byte("body"), headers, "secret", "X-Hub-Signature-256") 108 if err == nil { 109 t.Fatal("expected error for invalid hex") 110 } 111} 112 113func TestHMACSHA1_invalidSignature(t *testing.T) { 114 v, _ := NewVerifier("hmac-sha1") 115 headers := http.Header{"X-Hub-Signature": {"sha1=deadbeef"}} 116 err := v.Verify([]byte("body"), headers, "secret", "X-Hub-Signature") 117 if err == nil { 118 t.Fatal("expected error for invalid signature") 119 } 120}