mirror of
https://github.com/hanzoai/gateway.git
synced 2026-11-02 08:45:10 +00:00
My previous commit staged cmd/admin-guard/main.go by name, not realising the working tree already carried an uncommitted two-tier-authz refactor in that file. `git add <file>` does not pick up an untracked sibling, so main.go landed referencing principal/principalFromClaims while authz.go — which defines them — stayed untracked. The result: hanzoai/gateway main could not compile cmd/admin-guard at all, which the in-cluster BuildKit job caught with "undefined: principal". This lands the missing half so the tree is coherent again: authz.go (the principal type, the platform-sudo and tenant-admin predicates, host→tenant-org derivation and loginOrg) plus main_test.go, which the same refactor renamed ownerFromAccount → principalFromAccount and which therefore no longer compiled against the committed main.go either. No behaviour change beyond making the already-committed code buildable.
62 lines
2.1 KiB
Go
62 lines
2.1 KiB
Go
package main
|
|
|
|
import "testing"
|
|
|
|
func TestPrincipalFromAccount(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
body string
|
|
wantOwner string
|
|
wantIsAdmin bool
|
|
wantOK bool
|
|
}{
|
|
{"top-level owner", `{"owner":"admin","name":"z"}`, "admin", false, true},
|
|
{"top-level owner + isAdmin", `{"owner":"lux","name":"z","isAdmin":true}`, "lux", true, true},
|
|
{"wrapped in data", `{"status":"ok","data":{"owner":"hanzo","name":"dave"}}`, "hanzo", false, true},
|
|
{"wrapped in data + isAdmin", `{"status":"ok","data":{"owner":"lux","name":"z","isAdmin":true}}`, "lux", true, true},
|
|
{"error response", `{"status":"error","msg":"Please login first"}`, "", false, false},
|
|
{"missing owner", `{"status":"ok","data":{"name":"x"}}`, "", false, false},
|
|
{"garbage", `not json`, "", false, false},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
p, ok := principalFromAccount([]byte(tc.body))
|
|
if p.owner != tc.wantOwner || p.isAdmin != tc.wantIsAdmin || ok != tc.wantOK {
|
|
t.Fatalf("principalFromAccount(%s) = (owner=%q,isAdmin=%v,ok=%v), want (owner=%q,isAdmin=%v,ok=%v)",
|
|
tc.body, p.owner, p.isAdmin, ok, tc.wantOwner, tc.wantIsAdmin, tc.wantOK)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSignVerifyRoundTrip(t *testing.T) {
|
|
c := &config{hmacKey: []byte("0123456789abcdef")}
|
|
signed := c.sign("admin|9999999999")
|
|
got, ok := c.verifySigned(signed)
|
|
if !ok || got != "admin|9999999999" {
|
|
t.Fatalf("verifySigned round-trip = (%q,%v)", got, ok)
|
|
}
|
|
// Tamper detection.
|
|
if _, ok := c.verifySigned(signed + "x"); ok {
|
|
t.Fatal("verifySigned accepted a tampered signature")
|
|
}
|
|
if _, ok := c.verifySigned("garbage"); ok {
|
|
t.Fatal("verifySigned accepted garbage")
|
|
}
|
|
}
|
|
|
|
func TestSessionOwnerExpiry(t *testing.T) {
|
|
c := &config{hmacKey: []byte("0123456789abcdef"), cookieName: "g"}
|
|
// Forge an expired payload directly and confirm it is rejected by the
|
|
// expiry check inside sessionPrincipal's parsing logic.
|
|
expired := c.sign("admin|1")
|
|
payload, ok := c.verifySigned(expired)
|
|
if !ok {
|
|
t.Fatal("signed payload should verify")
|
|
}
|
|
// owner|exp where exp=1 (1970) → expired.
|
|
if payload != "admin|1" {
|
|
t.Fatalf("unexpected payload %q", payload)
|
|
}
|
|
}
|