Files
felhom.eu/hub/internal/api/r1140_accesslog_test.go
T
admin 7d64038f02
gates / gates (push) Successful in 6m45s
Hub v0.158.0 code (built, NOT deployed): agent-only vouch, R-895 snapshot alarms, the hub's own 90-day access log (R-1140 A); installer --rotate-recovery-only (R-1141); 02/03/05/09 + break-glass
Hub: the R-120 golden guard judges only a CHANGED golden selection; offsite_snapshots_vanished /
_unexplained (operator-only, hub-origin) on the 07:10 listing; internal/accesslog writes path-only
lines to /data/access-log, 90 days. Installer: --rotate-recovery-only runs step 4b alone (rides
the next installer tag). 03: the orphan check runs after a failed backup (agent 6545ccc). 02: the
allow-list is empty, appdata_folders (controller v0.329.0). All red-proofed.
2026-10-17 23:31:34 +02:00

62 lines
2.2 KiB
Go

package api
import (
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
"gitea.dooplex.hu/admin/felhom-hub/internal/accesslog"
"gitea.dooplex.hu/admin/felhom-hub/internal/store"
)
// R-1140: the box API's auth helpers mark the identity KIND they established, and the access log writes it — never
// the key. One request per kind (customer, host, global) and one refused; the key values are the negative controls.
func TestAccessLog_APIMarksTheIdentityKindNeverTheKey(t *testing.T) {
h, st, _ := newTestHandler(t)
if err := st.SaveCustomerConfig(&store.CustomerConfig{CustomerID: "c1", APIKey: "CUSTKEY-r1140-aaaa", RetrievalPassword: "p", ConfigJSON: "{}"}); err != nil {
t.Fatal(err)
}
st.UpsertHost(&store.Host{HostID: "h1", CustomerID: "c1", APIKey: "HOSTKEY-r1140-bbbb"})
dir := t.TempDir()
l := accesslog.New(accesslog.Options{Dir: dir})
mw := l.Middleware(h)
for _, c := range []struct{ method, path, key string }{
{"POST", "/api/v1/preferences", "CUSTKEY-r1140-aaaa"},
{"GET", "/api/v1/hosts/h1/jobs", "HOSTKEY-r1140-bbbb"},
{"GET", "/api/v1/customers", globalKey},
{"GET", "/api/v1/customers", "WRONGKEY-r1140-cccc"},
} {
r := httptest.NewRequest(c.method, c.path, strings.NewReader("{}"))
r.Header.Set("Authorization", "Bearer "+c.key)
mw.ServeHTTP(httptest.NewRecorder(), r)
}
l.Close()
ents, _ := os.ReadDir(dir)
if len(ents) != 1 {
t.Fatalf("%d file(s) in the access log dir, want 1", len(ents))
}
raw, _ := os.ReadFile(filepath.Join(dir, ents[0].Name()))
got := string(raw)
lines := strings.Split(strings.TrimSpace(got), "\n")
if len(lines) != 4 {
t.Fatalf("%d line(s), want 4:\n%s", len(lines), got)
}
for i, want := range []string{"POST /api/v1/preferences", "GET /api/v1/hosts/h1/jobs", "GET /api/v1/customers", "GET /api/v1/customers"} {
if !strings.Contains(lines[i], want) {
t.Errorf("line %d = %q, want %q", i, lines[i], want)
}
}
for i, kind := range []string{"auth=customer", "auth=host", "auth=global", "auth=-"} {
if !strings.HasSuffix(lines[i], kind) {
t.Errorf("line %d = %q, want it to end with %s", i, lines[i], kind)
}
}
for _, k := range []string{"CUSTKEY", "HOSTKEY", globalKey, "WRONGKEY"} {
if strings.Contains(got, k) {
t.Errorf("a key value reached the access log: %q", k)
}
}
}