chore: establish local platform baseline
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package mockalertreceiver
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestReceiverVerifiesAndRecordsSignedDelivery(t *testing.T) {
|
||||
t.Parallel()
|
||||
secret := "test-alert-receiver-secret-at-least-32-bytes"
|
||||
now := time.Unix(1_800_000_000, 0).UTC()
|
||||
server, err := New(Options{Secret: secret, ClockSkew: 5 * time.Minute}, slog.New(slog.NewTextHandler(io.Discard, nil)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
server.now = func() time.Time { return now }
|
||||
httpServer := httptest.NewServer(server.Handler())
|
||||
defer httpServer.Close()
|
||||
body, _ := json.Marshal(envelope{EventID: "10000000-0000-0000-0000-000000000001", EventType: "alert.webhook_test_requested", Data: json.RawMessage(`{"test_ref":"10000000-0000-0000-0000-000000000099"}`)})
|
||||
timestamp := strconv.FormatInt(now.Unix(), 10)
|
||||
request, _ := http.NewRequest(http.MethodPost, httpServer.URL+"/webhooks/alerts", bytes.NewReader(body))
|
||||
request.Header.Set("X-Voice-Event-ID", "10000000-0000-0000-0000-000000000001")
|
||||
request.Header.Set("X-Voice-Timestamp", timestamp)
|
||||
request.Header.Set("X-Voice-Signature", testSignature([]byte(secret), timestamp, body))
|
||||
response, err := http.DefaultClient.Do(request)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
response.Body.Close()
|
||||
if response.StatusCode != http.StatusNoContent {
|
||||
t.Fatalf("delivery status=%d", response.StatusCode)
|
||||
}
|
||||
response, err = http.Get(httpServer.URL + "/events?test_ref=10000000-0000-0000-0000-000000000099")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
var result struct {
|
||||
Items []Event `json:"items"`
|
||||
}
|
||||
if err = json.NewDecoder(response.Body).Decode(&result); err != nil || len(result.Items) != 1 || result.Items[0].EventType != "alert.webhook_test_requested" {
|
||||
t.Fatalf("events=%+v err=%v", result.Items, err)
|
||||
}
|
||||
|
||||
invalid, _ := http.NewRequest(http.MethodPost, httpServer.URL+"/webhooks/alerts", bytes.NewReader(body))
|
||||
invalid.Header.Set("X-Voice-Event-ID", "10000000-0000-0000-0000-000000000001")
|
||||
invalid.Header.Set("X-Voice-Timestamp", timestamp)
|
||||
invalid.Header.Set("X-Voice-Signature", "v1=00")
|
||||
response, err = http.DefaultClient.Do(invalid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
response.Body.Close()
|
||||
if response.StatusCode != http.StatusUnauthorized {
|
||||
t.Fatalf("invalid signature status=%d", response.StatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
func testSignature(secret []byte, timestamp string, body []byte) string {
|
||||
mac := hmac.New(sha256.New, secret)
|
||||
_, _ = mac.Write([]byte(timestamp + "."))
|
||||
_, _ = mac.Write(body)
|
||||
return "v1=" + hex.EncodeToString(mac.Sum(nil))
|
||||
}
|
||||
Reference in New Issue
Block a user