fix(llm): require get permission when resolving llm_id (#25627)

Fetch the referenced LLM with the caller session before filling access URL fields.

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 13:19:53 +08:00
committed by GitHub
parent 19d63a7a36
commit 4b9f523424
5 changed files with 29 additions and 10 deletions

View File

@@ -131,11 +131,10 @@ func resolveHermesAgentSpec(ctx context.Context, userCred mcclient.TokenCredenti
return out, nil
}
llmObj, err := models.GetLLMManager().FetchByIdOrName(ctx, userCred, out.LLMId)
targetLLM, err := models.FetchAccessibleLLM(ctx, userCred, out.LLMId)
if err != nil {
return nil, errors.Wrapf(err, "fetch target LLM %s", out.LLMId)
}
targetLLM := llmObj.(*models.SLLM)
targetSku, err := targetLLM.GetLLMSku(targetLLM.LLMSkuId)
if err != nil {
return nil, errors.Wrap(err, "fetch target LLM SKU")

View File

@@ -20,6 +20,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/llm/options"
llmutils "yunion.io/x/onecloud/pkg/llm/utils"
@@ -53,6 +54,23 @@ func GetLLMManager() *SLLMManager {
return llmManager
}
func requireLLMGetAllowed(ctx context.Context, userCred mcclient.TokenCredential, llm *SLLM) error {
return db.IsObjectRbacAllowed(ctx, llm, userCred, policy.PolicyActionGet)
}
// FetchAccessibleLLM fetches an LLM by id or name and requires get permission.
func FetchAccessibleLLM(ctx context.Context, userCred mcclient.TokenCredential, idStr string) (*SLLM, error) {
llmObj, err := GetLLMManager().FetchByIdOrName(ctx, userCred, strings.TrimSpace(idStr))
if err != nil {
return nil, err
}
llm := llmObj.(*SLLM)
if err := requireLLMGetAllowed(ctx, userCred, llm); err != nil {
return nil, err
}
return llm, nil
}
type SLLMManager struct {
SLLMBaseManager
}

View File

@@ -21,6 +21,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
"yunion.io/x/onecloud/pkg/httperrors"
bench "yunion.io/x/onecloud/pkg/llm/benchmark"
"yunion.io/x/onecloud/pkg/llm/options"
@@ -344,6 +345,9 @@ func resolveBenchmarkTarget(ctx context.Context, userCred mcclient.TokenCredenti
return nil, nil, errors.Wrap(err, "fetch LLMDeployment")
}
dep := depObj.(*SLLMDeployment)
if err := db.IsObjectRbacAllowed(ctx, dep, userCred, policy.PolicyActionGet); err != nil {
return nil, nil, err
}
llm := &SLLM{}
err = GetLLMManager().Query().
Equals("llm_deployment_id", dep.Id).
@@ -362,11 +366,10 @@ func resolveBenchmarkTarget(ctx context.Context, userCred mcclient.TokenCredenti
if input.LLMId == "" {
return nil, nil, errors.Wrap(httperrors.ErrMissingParameter, "llm_id or llm_deployment_id")
}
llmObj, err := GetLLMManager().FetchByIdOrName(ctx, userCred, input.LLMId)
llm, err := FetchAccessibleLLM(ctx, userCred, input.LLMId)
if err != nil {
return nil, nil, errors.Wrap(err, "fetch LLM")
}
llm := llmObj.(*SLLM)
if llm.Status != api.LLM_STATUS_RUNNING {
return nil, nil, errors.Wrapf(httperrors.ErrInvalidStatus, "llm %s status is %s", llm.Name, llm.Status)
}

View File

@@ -217,11 +217,10 @@ func resolveRouterAgentLLM(ctx context.Context, userCred mcclient.TokenCredentia
if llmId == nil || strings.TrimSpace(*llmId) == "" {
return nil
}
llmObj, err := GetLLMManager().FetchByIdOrName(ctx, userCred, strings.TrimSpace(*llmId))
llm, err := FetchAccessibleLLM(ctx, userCred, *llmId)
if err != nil {
return errors.Wrapf(err, "fetch LLM by id %s", *llmId)
}
llm := llmObj.(*SLLM)
*llmId = llm.Id
info, err := llm.GetLLMAccessUrlInfo(ctx, userCred, query)
if err != nil {

View File

@@ -230,11 +230,10 @@ func (man *SMCPAgentManager) ValidateCreateData(ctx context.Context, userCred mc
// 如果提供了 llm_id则通过 LLM 获取 llm_url 和 model
if len(input.LLMId) > 0 {
llmObj, err := GetLLMManager().FetchByIdOrName(ctx, userCred, input.LLMId)
llm, err := FetchAccessibleLLM(ctx, userCred, input.LLMId)
if err != nil {
return input, errors.Wrapf(err, "fetch LLM by id %s", input.LLMId)
}
llm := llmObj.(*SLLM)
input.LLMId = llm.Id
llmUrl, err := llm.GetLLMAccessUrlInfo(ctx, userCred, query)
if err != nil {
@@ -298,11 +297,12 @@ func (man *SMCPAgentManager) ValidateUpdateData(ctx context.Context, userCred mc
// 如果提供了 llm_id则通过 LLM 获取 llm_url 和 model
if input.LLMId != nil && len(*input.LLMId) > 0 {
llmObj, err := GetLLMManager().FetchByIdOrName(ctx, userCred, *input.LLMId)
llm, err := FetchAccessibleLLM(ctx, userCred, *input.LLMId)
if err != nil {
return input, errors.Wrapf(err, "fetch LLM by id %s", *input.LLMId)
}
llm := llmObj.(*SLLM)
llmId := llm.Id
input.LLMId = &llmId
llmUrl, err := llm.GetLLMAccessUrlInfo(ctx, userCred, query)
if err != nil {
return input, errors.Wrapf(err, "get LLM URL from LLM %s", *input.LLMId)