mirror of
https://github.com/hanzoai/commerce.git
synced 2026-10-30 15:08:42 +00:00
IsSuperAdmin folded the case of the home org and fell back to the owner claim, the org of the application that minted the token, and the money bits were granted on X-User-Owner == admin. Cloud writes X-User-Owner for an admin-org application and an admin-org person's API key as well as for a person, so either could mint money and edit the catalog here while being nobody in the rest of the same process. Every gate now reads X-User-IsAdmin, which the edge strips and writes from authz.Claims.Sudo alone; the standalone EdgeAuth decides it with that predicate over the verified token's signed membership set. X-User-IsAdmin no longer doubles as the org-admin bit, which is X-User-IsOrgAdmin. No machine is SuperAdmin. Global admin is SuperAdmin wherever it named this predicate.
43 lines
1.8 KiB
Go
43 lines
1.8 KiB
Go
// Copyright (c) 2014-present Hanzo AI, Inc.
|
|
// Licensed under MIT OR Apache-2.0. See LICENSE-MIT and LICENSE-APACHE.
|
|
//
|
|
// Package organization — M1 regression: the "platform" org-name namespace
|
|
// bypass is gone.
|
|
//
|
|
// Previously Organization.Namespace() returned "" (the global/cross-org
|
|
// datastore namespace where every org's records live) when Name=="platform",
|
|
// keyed purely on an org-NAME string and fully decoupled from real
|
|
// platform-admin identity. Anyone who could land in (or forge owner=) an org
|
|
// named "platform" got a cross-org datastore view (Red — privilege escalation
|
|
// via the empty namespace). Cross-org access is now gated EXCLUSIVELY on
|
|
// auth.IAMClaims.IsSuperAdmin() at the handler layer; the model never grants it
|
|
// by name.
|
|
package organization
|
|
|
|
import "testing"
|
|
|
|
// TestNamespace_NoPlatformBypass pins the fix: "platform" is just another org
|
|
// name, strictly scoped to itself — never the empty/global namespace.
|
|
func TestNamespace_NoPlatformBypass(t *testing.T) {
|
|
if ns := (Organization{Name: "platform"}).Namespace(); ns != "platform" {
|
|
t.Fatalf("platform org namespace = %q, want \"platform\" (empty-namespace bypass must be removed)", ns)
|
|
}
|
|
}
|
|
|
|
// TestNamespace_StrictScoping proves ordinary orgs are scoped to their own
|
|
// name, and an empty name maps to the empty namespace with no special-casing.
|
|
func TestNamespace_StrictScoping(t *testing.T) {
|
|
cases := map[string]string{
|
|
"maxpower": "maxpower",
|
|
"hanzo": "hanzo",
|
|
"admin": "admin", // even the reserved admin org is name-scoped here;
|
|
// cross-org access is granted by IsSuperAdmin(), not by Namespace().
|
|
"": "",
|
|
}
|
|
for name, want := range cases {
|
|
if got := (Organization{Name: name}).Namespace(); got != want {
|
|
t.Errorf("Organization{Name:%q}.Namespace() = %q, want %q", name, got, want)
|
|
}
|
|
}
|
|
}
|