7d64038f02
gates / gates (push) Successful in 6m45s
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.
62 lines
2.2 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|