Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
61 lines
1.8 KiB
Go
61 lines
1.8 KiB
Go
package audit
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gitea.mynodes.xyz/ilker/llmgw/internal/store"
|
|
)
|
|
|
|
func TestNothingSecretIsRecorded(t *testing.T) {
|
|
got := Redact(FormFields(url.Values{
|
|
"current": {"old-pw"}, "new": {"new-pw"}, "password": {"pw"}, "csrf": {"tok"},
|
|
"name": {"ok-name"}, "note": {"sk-proj-abcdefgh"},
|
|
}))
|
|
for _, secret := range []string{"old-pw", "new-pw", `"pw"`, "tok", "sk-proj"} {
|
|
if strings.Contains(got, secret) {
|
|
t.Errorf("%s recorded: %s", secret, got)
|
|
}
|
|
}
|
|
if !strings.Contains(got, "ok-name") {
|
|
t.Errorf("an ordinary field was dropped: %s", got)
|
|
}
|
|
nested := Redact(map[string]any{"external": map[string]any{"api_key": "x1", "url": "https://p"}})
|
|
if strings.Contains(nested, "x1") || !strings.Contains(nested, "https://p") {
|
|
t.Errorf("nested: %s", nested)
|
|
}
|
|
}
|
|
|
|
type memSink struct{ got []store.AuditEvent }
|
|
|
|
func (m *memSink) WriteAudit(_ context.Context, e store.AuditEvent) error {
|
|
m.got = append(m.got, e)
|
|
return nil
|
|
}
|
|
|
|
func TestEveryChangeToTheAdminAPIIsRecorded(t *testing.T) {
|
|
sink := &memSink{}
|
|
h := API(sink, func(*http.Request) string { return "ilker" }, nil, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusCreated)
|
|
}))
|
|
for _, req := range []*http.Request{
|
|
httptest.NewRequest("GET", "/api/v1/models", nil),
|
|
httptest.NewRequest("POST", "/api/v1/models", strings.NewReader(`{"name":"m1","external":{"api_key":"sk-1"}}`)),
|
|
httptest.NewRequest("DELETE", "/api/v1/nodes/n1", nil),
|
|
} {
|
|
h.ServeHTTP(httptest.NewRecorder(), req)
|
|
}
|
|
if len(sink.got) != 2 {
|
|
t.Fatalf("recorded %d: %+v", len(sink.got), sink.got)
|
|
}
|
|
e := sink.got[0]
|
|
if e.Actor != "ilker" || e.Action != "POST /api/v1/models" || e.Target != "m1" || e.Status != 201 ||
|
|
strings.Contains(e.Detail, "sk-1") || e.Source != "api" {
|
|
t.Errorf("%+v", e)
|
|
}
|
|
}
|