From 62956f870342c2f15eb3991d21a591564345dc19 Mon Sep 17 00:00:00 2001 From: doumicw Date: Fri, 14 Aug 2026 15:29:00 +0800 Subject: [PATCH 1/2] fix: validate permission module ownership --- .../presentation/permission_controller.go | 13 ++++- .../permission_controller_test.go | 55 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 manager/backend/services/footstone/presentation/permission_controller_test.go diff --git a/manager/backend/services/footstone/presentation/permission_controller.go b/manager/backend/services/footstone/presentation/permission_controller.go index dbf1406..d5506ca 100644 --- a/manager/backend/services/footstone/presentation/permission_controller.go +++ b/manager/backend/services/footstone/presentation/permission_controller.go @@ -134,7 +134,7 @@ func (p *PermissionController) ListMenus(_ context.Context, _ *ftpb.ListMenusReq // 开源版无细粒度 RBAC,但须校验调用方为有效已认证用户: // - user 为空或缺少角色 → 拒绝(防止绕过认证的越权访问) // - global 超级管理员 → 放通所有路径 -// - 普通已认证用户 → 放通(开源版默认所有已认证用户可访问) +// - 普通已认证用户 → 仅允许访问自身角色覆盖的 module_id func (p *PermissionController) HasPermission(_ context.Context, req *ftpb.HasPermissionRequest) (*ftpb.HasPermissionResponse, error) { if req == nil || req.User == nil { return &ftpb.HasPermissionResponse{Ok: false}, nil @@ -142,5 +142,16 @@ func (p *PermissionController) HasPermission(_ context.Context, req *ftpb.HasPer if len(req.User.Roles) == 0 { return &ftpb.HasPermissionResponse{Ok: false}, nil } + if req.User.GetIsSuperAdmin() { + return &ftpb.HasPermissionResponse{Ok: true}, nil + } + if req.ModuleId != "" { + for _, role := range req.User.Roles { + if role.GetModuleId() == req.ModuleId { + return &ftpb.HasPermissionResponse{Ok: true}, nil + } + } + return &ftpb.HasPermissionResponse{Ok: false}, nil + } return &ftpb.HasPermissionResponse{Ok: true}, nil } diff --git a/manager/backend/services/footstone/presentation/permission_controller_test.go b/manager/backend/services/footstone/presentation/permission_controller_test.go new file mode 100644 index 0000000..ac340ee --- /dev/null +++ b/manager/backend/services/footstone/presentation/permission_controller_test.go @@ -0,0 +1,55 @@ +package presentation + +import ( + "context" + "testing" + + ftpb "gitee.com/OpenCloudOS/ocmanager/manager/backend/protocol/footstone" +) + +func TestHasPermissionRejectsModuleIDOutsideUserRoles(t *testing.T) { + controller := &PermissionController{} + resp, err := controller.HasPermission(context.Background(), &ftpb.HasPermissionRequest{ + User: &ftpb.UserInfo{ + Roles: []*ftpb.ModuleRole{{ModuleId: "1", RoleId: "operator"}}, + }, + ModuleId: "2", + }) + if err != nil { + t.Fatalf("HasPermission: %v", err) + } + if resp.GetOk() { + t.Fatal("HasPermission allowed module_id outside user roles") + } +} + +func TestHasPermissionAllowsOwnedModuleIDAndSuperAdmin(t *testing.T) { + controller := &PermissionController{} + + resp, err := controller.HasPermission(context.Background(), &ftpb.HasPermissionRequest{ + User: &ftpb.UserInfo{ + Roles: []*ftpb.ModuleRole{{ModuleId: "1", RoleId: "operator"}}, + }, + ModuleId: "1", + }) + if err != nil { + t.Fatalf("HasPermission owned module: %v", err) + } + if !resp.GetOk() { + t.Fatal("HasPermission rejected owned module_id") + } + + resp, err = controller.HasPermission(context.Background(), &ftpb.HasPermissionRequest{ + User: &ftpb.UserInfo{ + IsSuperAdmin: true, + Roles: []*ftpb.ModuleRole{{ModuleId: "global", RoleId: "global"}}, + }, + ModuleId: "2", + }) + if err != nil { + t.Fatalf("HasPermission super admin: %v", err) + } + if !resp.GetOk() { + t.Fatal("HasPermission rejected super admin") + } +} -- Gitee From 2fa851aaa0bda0b3b21b495142b54be5bc8b220c Mon Sep 17 00:00:00 2001 From: doumicw Date: Mon, 17 Aug 2026 21:44:12 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix(permission):=20=E6=8C=89=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E8=AF=86=E5=88=AB=E8=B6=85=E7=AE=A1=E5=B9=B6=E6=8B=92?= =?UTF-8?q?=E7=BB=9D=E7=A9=BA=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/permission_controller.go | 20 ++++++++++--------- .../permission_controller_test.go | 16 +++++++++++++-- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/manager/backend/services/footstone/presentation/permission_controller.go b/manager/backend/services/footstone/presentation/permission_controller.go index d5506ca..4653b1b 100644 --- a/manager/backend/services/footstone/presentation/permission_controller.go +++ b/manager/backend/services/footstone/presentation/permission_controller.go @@ -142,16 +142,18 @@ func (p *PermissionController) HasPermission(_ context.Context, req *ftpb.HasPer if len(req.User.Roles) == 0 { return &ftpb.HasPermissionResponse{Ok: false}, nil } - if req.User.GetIsSuperAdmin() { - return &ftpb.HasPermissionResponse{Ok: true}, nil - } - if req.ModuleId != "" { - for _, role := range req.User.Roles { - if role.GetModuleId() == req.ModuleId { - return &ftpb.HasPermissionResponse{Ok: true}, nil - } + for _, role := range req.User.Roles { + if role.GetRoleId() == "global" { + return &ftpb.HasPermissionResponse{Ok: true}, nil } + } + if req.ModuleId == "" { return &ftpb.HasPermissionResponse{Ok: false}, nil } - return &ftpb.HasPermissionResponse{Ok: true}, nil + for _, role := range req.User.Roles { + if role.GetModuleId() == req.ModuleId { + return &ftpb.HasPermissionResponse{Ok: true}, nil + } + } + return &ftpb.HasPermissionResponse{Ok: false}, nil } diff --git a/manager/backend/services/footstone/presentation/permission_controller_test.go b/manager/backend/services/footstone/presentation/permission_controller_test.go index ac340ee..2475ebc 100644 --- a/manager/backend/services/footstone/presentation/permission_controller_test.go +++ b/manager/backend/services/footstone/presentation/permission_controller_test.go @@ -41,8 +41,7 @@ func TestHasPermissionAllowsOwnedModuleIDAndSuperAdmin(t *testing.T) { resp, err = controller.HasPermission(context.Background(), &ftpb.HasPermissionRequest{ User: &ftpb.UserInfo{ - IsSuperAdmin: true, - Roles: []*ftpb.ModuleRole{{ModuleId: "global", RoleId: "global"}}, + Roles: []*ftpb.ModuleRole{{ModuleId: "global", RoleId: "global"}}, }, ModuleId: "2", }) @@ -53,3 +52,16 @@ func TestHasPermissionAllowsOwnedModuleIDAndSuperAdmin(t *testing.T) { t.Fatal("HasPermission rejected super admin") } } + +func TestHasPermissionRejectsEmptyModuleIDForRegularUser(t *testing.T) { + controller := &PermissionController{} + resp, err := controller.HasPermission(context.Background(), &ftpb.HasPermissionRequest{ + User: &ftpb.UserInfo{Roles: []*ftpb.ModuleRole{{ModuleId: "1", RoleId: "operator"}}}, + }) + if err != nil { + t.Fatalf("HasPermission: %v", err) + } + if resp.GetOk() { + t.Fatal("HasPermission allowed an empty module_id for a regular user") + } +} -- Gitee