Fail closed on Go SDK idempotency entropy errors
This commit is contained in:
@@ -3,6 +3,7 @@ package attesto
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
@@ -135,3 +136,67 @@ func TestRelayLocalVaultEventReturnsMarshalError(t *testing.T) {
|
||||
t.Fatalf("request was sent after marshal failure")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGeneratedIdempotencyKeyFailsClosedOnEntropyError(t *testing.T) {
|
||||
originalRead := secureRandomRead
|
||||
secureRandomRead = func([]byte) (int, error) {
|
||||
return 0, errors.New("entropy unavailable")
|
||||
}
|
||||
t.Cleanup(func() { secureRandomRead = originalRead })
|
||||
|
||||
called := false
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
called = true
|
||||
t.Fatalf("request should not be sent when idempotency key generation fails")
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client, err := NewClient(testAPIKey, WithBaseURL(server.URL), WithMaxRetries(1))
|
||||
if err != nil {
|
||||
t.Fatalf("client: %v", err)
|
||||
}
|
||||
|
||||
_, err = client.CreateStream(context.Background(), StreamCreateInput{UseCase: "ai-governance", PolicyID: "policy-main"})
|
||||
if err == nil || !strings.Contains(err.Error(), "generate idempotency key") {
|
||||
t.Fatalf("expected idempotency entropy error, got %v", err)
|
||||
}
|
||||
if called {
|
||||
t.Fatalf("request was sent after idempotency generation failure")
|
||||
}
|
||||
}
|
||||
|
||||
func TestExplicitIdempotencyKeyBypassesEntropyGeneration(t *testing.T) {
|
||||
originalRead := secureRandomRead
|
||||
secureRandomRead = func([]byte) (int, error) {
|
||||
return 0, errors.New("entropy unavailable")
|
||||
}
|
||||
t.Cleanup(func() { secureRandomRead = originalRead })
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get("Idempotency-Key") != "fixed-key" {
|
||||
t.Fatalf("explicit idempotency key missing: %q", r.Header.Get("Idempotency-Key"))
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(Stream{
|
||||
StreamID: "str_fixed", SystemID: "sys_fixed", UseCase: "ai-governance", PolicyID: "policy-main", Status: "active", Created: true,
|
||||
})
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client, err := NewClient(testAPIKey, WithBaseURL(server.URL), WithMaxRetries(1))
|
||||
if err != nil {
|
||||
t.Fatalf("client: %v", err)
|
||||
}
|
||||
|
||||
stream, err := client.CreateStream(
|
||||
context.Background(),
|
||||
StreamCreateInput{UseCase: "ai-governance", PolicyID: "policy-main"},
|
||||
RequestOptions{IdempotencyKey: "fixed-key"},
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("create stream with explicit idempotency key: %v", err)
|
||||
}
|
||||
if stream.StreamID != "str_fixed" {
|
||||
t.Fatalf("unexpected stream: %#v", stream)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user