fix(identity): check assume login with system scope and target roles (#25629)

Keep the caller session when authorizing assume and reuse join-project role checks.

Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jian Qiu
2026-09-10 12:14:33 +08:00
committed by GitHub
parent f208976ef0
commit b1d1cad973
2 changed files with 49 additions and 14 deletions

View File

@@ -55,18 +55,6 @@ func authUserByAssume(ctx context.Context, input mcclient.SAuthenticationInputV3
return nil, errors.Wrap(err, "fetch scoped project")
}
var requireScope rbacscope.TRbacScope
if adminToken.ProjectId == scopedProject.Id {
requireScope = rbacscope.ScopeProject
} else if adminToken.DomainId == scopedProject.DomainId {
requireScope = rbacscope.ScopeDomain
} else {
requireScope = rbacscope.ScopeSystem
}
adminToken.ProjectId = scopedProject.Id
adminToken.DomainId = scopedProject.DomainId
adminTokenCred, err := adminToken.GetSimpleUserCred(input.Auth.Identity.Token.Id)
if err != nil {
return nil, errors.Wrap(err, "get admin token credential")
@@ -90,8 +78,8 @@ func authUserByAssume(ctx context.Context, input mcclient.SAuthenticationInputV3
}
if adminTokenCred.GetUserId() != targetUser.Id {
if policy.PolicyManager.Allow(requireScope, adminTokenCred, api.SERVICE_TYPE, "tokens", "perform", "assume").Result.IsDeny() {
return nil, httperrors.NewForbiddenError("%s not allow to assume user in project %s", adminTokenCred.GetUserName(), scopedProject.Name)
if err := checkAssumeAllowed(adminTokenCred, targetUser.Id, scopedProject); err != nil {
return nil, err
}
}
@@ -100,3 +88,21 @@ func authUserByAssume(ctx context.Context, input mcclient.SAuthenticationInputV3
return targetUser, nil
}
func checkAssumeAllowed(adminTokenCred mcclient.TokenCredential, targetUserId string, scopedProject *models.SProject) error {
if policy.PolicyManager.Allow(rbacscope.ScopeSystem, adminTokenCred, api.SERVICE_TYPE, "tokens", "perform", "assume").Result.IsDeny() {
return httperrors.NewForbiddenError("%s not allow to assume user in project %s", adminTokenCred.GetUserName(), scopedProject.Name)
}
roles, err := models.AssignmentManager.FetchUserProjectRoles(targetUserId, scopedProject.Id)
if err != nil {
return errors.Wrap(err, "fetch target user roles")
}
roleIds := make([]string, len(roles))
for i := range roles {
roleIds[i] = roles[i].Id
}
if err := models.ValidateJoinProjectRoles(adminTokenCred, scopedProject.Id, roleIds); err != nil {
return errors.Wrap(err, "validate assume target roles")
}
return nil
}

View File

@@ -0,0 +1,29 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tokens
import (
"context"
"testing"
"yunion.io/x/onecloud/pkg/mcclient"
)
func TestAuthUserByAssumeRequiresAdminToken(t *testing.T) {
_, err := authUserByAssume(context.Background(), mcclient.SAuthenticationInputV3{})
if err == nil {
t.Fatal("expected error when admin token is missing")
}
}