feat(rbac): agent RBAC/ACL scenes and resource-locator check bundles (#41768)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Xiyuan Chenandautofix-ci[bot] authored and GitHub committed 2026-09-07 04:39:43 +00:00
1 parent 60e983c493
commit 86134ea99e
152 files changed
+5360 -3405

No files matched your search

+4 -12
View File
@@ -6,7 +6,7 @@ from enum import StrEnum
from pydantic import BaseModel, ConfigDict, Field
from werkzeug.exceptions import InternalServerError
from core.rbac import RBACPermission, RBACResourceScope
from controllers.common.rbac import RBACCheck
from libs.oauth_bearer import Scope, TokenType
from models.account import Account, Tenant, TenantAccountRole
from models.model import App, EndUser
@@ -25,23 +25,15 @@ class ExternalIdentity(BaseModel):
issuer: str | None = None
class RBACRequirement(BaseModel):
model_config = ConfigDict(frozen=True)
resource_type: RBACResourceScope
scene: RBACPermission
resource_required: bool = True
class RequestContext(BaseModel):
model_config = ConfigDict(frozen=True)
model_config = ConfigDict(frozen=True, arbitrary_types_allowed=True)
token_type: TokenType
scope: Scope | None = None
path_params: dict[str, str]
workspace_membership: bool = False
allowed_roles: frozenset[TenantAccountRole] | None = None
rbac: RBACRequirement | None = None
rbac: RBACCheck | None = None
class AuthData(BaseModel):
@@ -58,7 +50,7 @@ class AuthData(BaseModel):
path_params: dict[str, str] = Field(default_factory=dict)
allowed_roles: frozenset[TenantAccountRole] | None = None
rbac: RBACRequirement | None = None
rbac: RBACCheck | None = None
app: App | None = None
tenant: Tenant | None = None
+6 -6
View File
@@ -17,11 +17,11 @@ from flask_login import user_logged_in
from werkzeug.exceptions import Forbidden, NotFound, Unauthorized
from configs import dify_config
from controllers.common.rbac import RBACCheck
from controllers.openapi._audit import emit_wrong_surface
from controllers.openapi.auth.data import (
AuthData,
ExternalIdentity,
RBACRequirement,
RequestContext,
)
from controllers.openapi.auth.flow import When
@@ -61,7 +61,7 @@ class AuthPipeline:
scope: Scope | None,
workspace_membership: bool = False,
allowed_roles: frozenset[TenantAccountRole] | None = None,
rbac: RBACRequirement | None = None,
rbac: RBACCheck | None = None,
) -> Any:
req_ctx = RequestContext(
token_type=identity.token_type,
@@ -135,7 +135,7 @@ class PipelineRouter:
require_valid_enterprise_license: bool = False,
workspace_membership: bool = False,
allowed_roles: frozenset[TenantAccountRole] | None = None,
rbac: RBACRequirement | None = None,
rbac: RBACCheck | None = None,
) -> Callable:
return self._make_decorator(
scope=scope,
@@ -155,7 +155,7 @@ class PipelineRouter:
edition: frozenset[DeploymentEdition] | None = None,
require_valid_enterprise_license: bool = False,
allowed_roles: frozenset[TenantAccountRole] | None = None,
rbac: RBACRequirement | None = None,
rbac: RBACCheck | None = None,
) -> Callable:
return self._make_decorator(
scope=scope,
@@ -176,7 +176,7 @@ class PipelineRouter:
require_valid_enterprise_license: bool,
workspace_membership: bool,
allowed_roles: frozenset[TenantAccountRole] | None,
rbac: RBACRequirement | None,
rbac: RBACCheck | None,
) -> Callable:
def decorator(view: Callable) -> Callable:
@wraps(view)
@@ -210,7 +210,7 @@ class PipelineRouter:
require_valid_enterprise_license: bool,
workspace_membership: bool = False,
allowed_roles: frozenset[TenantAccountRole] | None = None,
rbac: RBACRequirement | None = None,
rbac: RBACCheck | None = None,
) -> Any:
# 404 not 403 — this edition doesn't expose the feature at all
if edition is not None and dify_config.DEPLOYMENT_EDITION not in edition:
+3 -5
View File
@@ -4,7 +4,7 @@ from flask import request
from werkzeug.exceptions import Forbidden, NotFound, UnprocessableEntity
from configs import dify_config
from controllers.common.wraps import enforce_rbac_access
from controllers.common.rbac import enforce_rbac_checks
from controllers.openapi.auth.data import AuthData, CallerKind
from extensions.ext_database import db
from libs.oauth_bearer import Scope, TokenType
@@ -62,12 +62,10 @@ def check_rbac_permission(data: AuthData) -> None:
return
if data.account_id is None or data.tenant is None:
raise Forbidden("rbac context missing")
enforce_rbac_access(
enforce_rbac_checks(
tenant_id=str(data.tenant.id),
account_id=str(data.account_id),
resource_type=req.resource_type,
scene=req.scene,
resource_required=req.resource_required,
checks=[req],
path_args=dict(data.path_params),
)