From 5b651488b081b65fda8a323f228e139adb79a35d Mon Sep 17 00:00:00 2001 From: Chia Date: Tue, 4 Aug 2026 19:58:52 +1200 Subject: Build AI gateway control plane and admin UI --- internal/auth/static_test.go | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 internal/auth/static_test.go (limited to 'internal/auth/static_test.go') diff --git a/internal/auth/static_test.go b/internal/auth/static_test.go new file mode 100644 index 0000000..cf54ba6 --- /dev/null +++ b/internal/auth/static_test.go @@ -0,0 +1,76 @@ +package auth + +import ( + "crypto/sha256" + "net/http" + "testing" + + "aigw/internal/domain" +) + +func TestStaticAuthenticator(t *testing.T) { + raw := `[{"key":"sk-client","key_id":"key-1","tenant_id":"tenant-1","project_id":"project-1","scopes":["inference"]}]` + authenticator, err := NewStatic(raw, false) + if err != nil { + t.Fatal(err) + } + + request, _ := http.NewRequest(http.MethodGet, "http://gateway.test/v1/models", nil) + request.Header.Set("Authorization", "Bearer sk-client") + principal, err := authenticator.Authenticate(request) + if err != nil { + t.Fatal(err) + } + if principal.TenantID != "tenant-1" || principal.ProjectID != "project-1" || principal.KeyID != "key-1" { + t.Fatalf("unexpected principal: %+v", principal) + } + + request.Header.Set("Authorization", "Bearer wrong") + if _, err := authenticator.Authenticate(request); err != ErrUnauthorized { + t.Fatalf("expected ErrUnauthorized, got %v", err) + } +} + +func TestDynamicAuthenticatorReplacesSnapshot(t *testing.T) { + oldHash := sha256.Sum256([]byte("sk-old")) + newHash := sha256.Sum256([]byte("sk-new")) + authenticator := NewDynamic([]HashedKeyRecord{{ + Hash: oldHash, + Principal: domain.Principal{ + KeyID: "old", TenantID: "tenant-1", ProjectID: "project-1", Scopes: []string{"inference"}, + }, + }}, false) + + request, _ := http.NewRequest(http.MethodGet, "http://gateway.test/v1/models", nil) + request.Header.Set("Authorization", "Bearer sk-old") + if _, err := authenticator.Authenticate(request); err != nil { + t.Fatalf("old key should initially authenticate: %v", err) + } + + authenticator.ReplaceHashed([]HashedKeyRecord{{ + Hash: newHash, + Principal: domain.Principal{ + KeyID: "new", TenantID: "tenant-1", ProjectID: "project-1", Scopes: []string{"inference"}, + }, + }}) + if _, err := authenticator.Authenticate(request); err != ErrUnauthorized { + t.Fatalf("old key remained valid after snapshot replacement: %v", err) + } + request.Header.Set("Authorization", "Bearer sk-new") + principal, err := authenticator.Authenticate(request) + if err != nil || principal.KeyID != "new" { + t.Fatalf("new key was not loaded: principal=%+v err=%v", principal, err) + } +} + +func TestStaticAuthenticatorAcceptsAnthropicHeader(t *testing.T) { + authenticator, err := NewStatic(`[{"key":"sk-client","key_id":"key-1","tenant_id":"tenant-1","project_id":"project-1"}]`, false) + if err != nil { + t.Fatal(err) + } + request, _ := http.NewRequest(http.MethodGet, "http://gateway.test/anthropic/v1/models", nil) + request.Header.Set("x-api-key", "sk-client") + if _, err := authenticator.Authenticate(request); err != nil { + t.Fatal(err) + } +} -- cgit v1.2.3