mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-09-19 17:50:12 +00:00
102 lines
3.1 KiB
Go
102 lines
3.1 KiB
Go
package rpc
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
|
|
"github.com/nezhahq/nezha/model"
|
|
"github.com/nezhahq/nezha/service/singleton"
|
|
)
|
|
|
|
// setupAuthAgentFixture seeds an in-memory DB and ServerShared with two
|
|
// servers belonging to different users so we can assert that a secret bound
|
|
// to user A cannot resolve a server UUID owned by user B.
|
|
func setupAuthAgentFixture(t *testing.T) func() {
|
|
t.Helper()
|
|
originalDB := singleton.DB
|
|
originalServerShared := singleton.ServerShared
|
|
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("open db: %v", err)
|
|
}
|
|
if err := db.AutoMigrate(&model.Server{}); err != nil {
|
|
t.Fatalf("migrate: %v", err)
|
|
}
|
|
if err := db.Create(&model.Server{
|
|
Common: model.Common{ID: 1, UserID: 100},
|
|
UUID: "uuid-alice",
|
|
Name: "alice-srv",
|
|
}).Error; err != nil {
|
|
t.Fatalf("create alice: %v", err)
|
|
}
|
|
if err := db.Create(&model.Server{
|
|
Common: model.Common{ID: 2, UserID: 200},
|
|
UUID: "uuid-bob",
|
|
Name: "bob-srv",
|
|
}).Error; err != nil {
|
|
t.Fatalf("create bob: %v", err)
|
|
}
|
|
singleton.DB = db
|
|
singleton.ServerShared = singleton.NewServerClass()
|
|
|
|
return func() {
|
|
singleton.DB = originalDB
|
|
singleton.ServerShared = originalServerShared
|
|
}
|
|
}
|
|
|
|
func TestAuthorizeAgentForUUIDAcceptsOwnedServer(t *testing.T) {
|
|
defer setupAuthAgentFixture(t)()
|
|
|
|
cid, hasID, err := authorizeAgentForUUID(100, "uuid-alice")
|
|
if err != nil {
|
|
t.Fatalf("alice with her own server UUID must not error, got %v", err)
|
|
}
|
|
if !hasID || cid != 1 {
|
|
t.Fatalf("expected (cid=1, hasID=true), got (cid=%d, hasID=%v)", cid, hasID)
|
|
}
|
|
}
|
|
|
|
// Core regression: an agent presenting user A's secret but user B's server
|
|
// UUID must be rejected. Previously the code returned the resolved server ID
|
|
// without verifying the UserID matched the secret owner, allowing same-tenant
|
|
// (and worse — cross-tenant if UUID leaks) server impersonation.
|
|
func TestAuthorizeAgentForUUIDRejectsForeignServerUUID(t *testing.T) {
|
|
defer setupAuthAgentFixture(t)()
|
|
|
|
_, _, err := authorizeAgentForUUID(100, "uuid-bob") // alice's secret + bob's UUID
|
|
if err == nil {
|
|
t.Fatalf("UUID owned by another user must be rejected")
|
|
}
|
|
}
|
|
|
|
func TestAuthorizeAgentForUUIDAllowsGlobalDefaultSecret(t *testing.T) {
|
|
defer setupAuthAgentFixture(t)()
|
|
|
|
cid, hasID, err := authorizeAgentForUUID(0, "uuid-bob")
|
|
if err != nil {
|
|
t.Fatalf("global default secret must be allowed to use existing UUIDs, got %v", err)
|
|
}
|
|
if !hasID || cid != 2 {
|
|
t.Fatalf("expected (cid=2, hasID=true), got (cid=%d, hasID=%v)", cid, hasID)
|
|
}
|
|
}
|
|
|
|
// An unknown UUID must NOT be treated as an impersonation attempt — it is
|
|
// the normal first-time registration path and the caller (Check) creates a
|
|
// new server bound to the secret owner.
|
|
func TestAuthorizeAgentForUUIDPermitsUnknownUUIDForRegistration(t *testing.T) {
|
|
defer setupAuthAgentFixture(t)()
|
|
|
|
cid, hasID, err := authorizeAgentForUUID(100, "uuid-never-seen-before")
|
|
if err != nil {
|
|
t.Fatalf("unknown UUID must be permitted for new registration, got %v", err)
|
|
}
|
|
if hasID {
|
|
t.Fatalf("hasID must be false for unknown UUID, got cid=%d", cid)
|
|
}
|
|
}
|