mcp and ucp
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
package ucp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSigningConfig_FromPEM(t *testing.T) {
|
||||
// PEM from the generated key pair (openssl ecparam -genkey -name prime256v1)
|
||||
pemData := `-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIDTssEctnrEqym80fx2jEVolTW+tWrHyo8fmbi8hMFWmoAoGCCqGSM49
|
||||
AwEHoUQDQgAEpnPksDSSMcNgUYT4++Z6XuS0V2p6TNMSjWBsgXOu7mo5Esoux+Cm
|
||||
y+C84ty5VUAdEpoDyNfWMeaAlHKGo+FjiQ==
|
||||
-----END EC PRIVATE KEY-----`
|
||||
|
||||
cfg, err := NewSigningConfigFromPEM([]byte(pemData), "k6n-ecdsa-2026")
|
||||
if err != nil {
|
||||
t.Fatalf("NewSigningConfigFromPEM failed: %v", err)
|
||||
}
|
||||
if cfg.KeyID != "k6n-ecdsa-2026" {
|
||||
t.Fatalf("expected key ID 'k6n-ecdsa-2026', got %q", cfg.KeyID)
|
||||
}
|
||||
if cfg.PrivateKey == nil {
|
||||
t.Fatal("expected non-nil private key")
|
||||
}
|
||||
if cfg.PrivateKey.Curve.Params().Name != "P-256" {
|
||||
t.Fatalf("expected P-256 curve, got %s", cfg.PrivateKey.Curve.Params().Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSigningConfig_InvalidPEM(t *testing.T) {
|
||||
_, err := NewSigningConfigFromPEM([]byte("not a pem"), "test")
|
||||
if err == nil {
|
||||
t.Fatal("expected error for invalid PEM")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithSigning_AddsHeaders(t *testing.T) {
|
||||
// Load the test key.
|
||||
cfg := mustLoadTestKey(t)
|
||||
|
||||
// A simple handler that returns a JSON response.
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
|
||||
})
|
||||
|
||||
wrapped := WithSigning(handler, cfg)
|
||||
req := httptest.NewRequest("GET", "/test", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
wrapped.ServeHTTP(rec, req)
|
||||
|
||||
// Check the response body.
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d", rec.Code)
|
||||
}
|
||||
|
||||
// Check that signature headers are present.
|
||||
sigInput := rec.Header().Get("Signature-Input")
|
||||
sig := rec.Header().Get("Signature")
|
||||
ts := rec.Header().Get("x-ucp-timestamp")
|
||||
|
||||
if sigInput == "" {
|
||||
t.Fatal("expected Signature-Input header")
|
||||
}
|
||||
if sig == "" {
|
||||
t.Fatal("expected Signature header")
|
||||
}
|
||||
if ts == "" {
|
||||
t.Fatal("expected x-ucp-timestamp header")
|
||||
}
|
||||
|
||||
// Verify the signature input format.
|
||||
if !strings.HasPrefix(sigInput, `sig1=(@status "content-type" "x-ucp-timestamp");`) {
|
||||
t.Fatalf("unexpected Signature-Input format: %q", sigInput)
|
||||
}
|
||||
if !strings.Contains(sigInput, `keyid="k6n-ecdsa-2026"`) {
|
||||
t.Fatalf("Signature-Input missing keyid: %q", sigInput)
|
||||
}
|
||||
if !strings.Contains(sigInput, `alg="ecdsa-p256"`) {
|
||||
t.Fatalf("Signature-Input missing alg: %q", sigInput)
|
||||
}
|
||||
|
||||
// Verify the signature format.
|
||||
if !strings.HasPrefix(sig, "sig1=:") || !strings.HasSuffix(sig, ":") {
|
||||
t.Fatalf("unexpected Signature format: %q", sig)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithSigning_NilConfig(t *testing.T) {
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("ok"))
|
||||
})
|
||||
|
||||
wrapped := WithSigning(handler, nil)
|
||||
req := httptest.NewRequest("GET", "/test", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
wrapped.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d", rec.Code)
|
||||
}
|
||||
if rec.Header().Get("Signature-Input") != "" {
|
||||
t.Fatal("expected no Signature-Input when signing is nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithSigning_DifferentStatuses(t *testing.T) {
|
||||
cfg := mustLoadTestKey(t)
|
||||
|
||||
for _, status := range []int{200, 201, 400, 404, 500} {
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(status)
|
||||
w.Write([]byte(`{}`))
|
||||
})
|
||||
|
||||
wrapped := WithSigning(handler, cfg)
|
||||
req := httptest.NewRequest("GET", "/test", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
wrapped.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != status {
|
||||
t.Fatalf("expected status %d, got %d", status, rec.Code)
|
||||
}
|
||||
if rec.Header().Get("Signature-Input") == "" {
|
||||
t.Fatalf("expected Signature-Input for status %d", status)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithSigning_WithUCPCartHandler(t *testing.T) {
|
||||
cfg := mustLoadTestKey(t)
|
||||
applier := newTestApplier()
|
||||
handler := CartHandler(applier)
|
||||
wrapped := WithSigning(handler, cfg)
|
||||
|
||||
// Create a cart through the wrapped handler.
|
||||
req := httptest.NewRequest("POST", "/", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
wrapped.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusCreated {
|
||||
t.Fatalf("expected 201, got %d", rec.Code)
|
||||
}
|
||||
|
||||
// Verify signed.
|
||||
if rec.Header().Get("Signature-Input") == "" {
|
||||
t.Fatal("expected Signature-Input on UCP cart response")
|
||||
}
|
||||
if rec.Header().Get("x-ucp-timestamp") == "" {
|
||||
t.Fatal("expected x-ucp-timestamp on UCP cart response")
|
||||
}
|
||||
}
|
||||
|
||||
// mustLoadTestKey loads the test PEM for signing tests.
|
||||
func mustLoadTestKey(t testing.TB) *SigningConfig {
|
||||
t.Helper()
|
||||
pemData := `-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIDTssEctnrEqym80fx2jEVolTW+tWrHyo8fmbi8hMFWmoAoGCCqGSM49
|
||||
AwEHoUQDQgAEpnPksDSSMcNgUYT4++Z6XuS0V2p6TNMSjWBsgXOu7mo5Esoux+Cm
|
||||
y+C84ty5VUAdEpoDyNfWMeaAlHKGo+FjiQ==
|
||||
-----END EC PRIVATE KEY-----`
|
||||
cfg, err := NewSigningConfigFromPEM([]byte(pemData), "k6n-ecdsa-2026")
|
||||
if err != nil {
|
||||
t.Fatalf("mustLoadTestKey: %v", err)
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
Reference in New Issue
Block a user