Apache Superset 二次开发实践:接入 AI Agent,并确保数据权限不被绕过

本文记录澈析 BI(Chexi BI)的开发实践。项目基于 Apache Superset 深度开发,增加了 AI Agent、MCP 工具服务、用户权限隔离和独立部署能力。澈析 BI 是独立产品,并非 Apache Software Foundation 官方发行版本。

一、为什么选择 Superset 做 AI BI

传统 BI 的主要操作包括连接数据源、编写 SQL、创建数据集、制作图表和搭建仪表盘。Apache Superset 已经提供了比较完整的数据可视化、SQL Lab、RBAC 和行级权限能力,适合作为智能 BI 的基础平台。

但接入大模型后,问题不只是"让 AI 生成 SQL"。真正需要解决的是:

  • AI 能看到哪些数据库和数据集?
  • AI 创建的图表属于哪个用户?
  • 不同角色能否通过 Agent 绕过页面权限?
  • 自然语言查询是否遵守行级安全规则?
  • AI 生成错误 SQL 时,如何限制影响范围?

因此,我们没有让 Agent 直接连接业务数据库,而是让它通过 Superset 的业务层和权限体系访问资源。

二、整体架构

复制代码
浏览器
  │
  ├── www.chexi.tech:公开产品官网
  │
  └── app.chexi.tech:登录后的 Superset 应用
                         │
                      Nginx / HTTPS
                         │
                 Gunicorn + Superset
                         │
          ┌──────────────┴──────────────┐
          │                             │
    PostgreSQL 元数据库            Redis 缓存
          │
          └──────── MCP Service ─────── AI Agent

MCP 服务作为独立进程运行,使用 FastMCP 提供标准化工具,但复用 Superset 的配置、元数据库、SQLAlchemy 模型和安全管理器。

目前工具覆盖数据集、数据库、图表、仪表盘等资源,例如:

复制代码
list_datasets        查询用户可见的数据集
query_dataset        查询已授权数据集
generate_chart       创建图表
get_chart_data       获取图表数据
generate_dashboard   创建仪表盘
list_dashboards      查询可见仪表盘

三、最重要的原则:AI 不能拥有额外权限

Agent 发起请求后,服务首先验证 JWT 或其他受支持的令牌,再将对应 Superset 用户写入当前请求上下文。

简化后的流程如下:

复制代码
def handle_agent_request(token: str):
    user = verify_token_and_resolve_user(token)

    if not user or not user.is_active:
        raise AuthenticationError()

    g.user = user
    return execute_tool_as_current_user()

之后继续使用 Superset 原有的安全能力:

  • Flask-AppBuilder RBAC 控制功能权限
  • DashboardAccessFilter 过滤看板
  • ChartAccessFilter 过滤图表
  • DatasourceFilter 过滤数据集
  • security_manager.raise_for_access() 校验具体数据资源
  • 数据集查询路径继续应用 Row Level Security

这意味着 Agent 只是用户的新操作入口,不是一个拥有管理员权限的超级账号。

需要特别注意:数据集 RLS 与任意 SQL 执行不是同一层安全边界。拥有 SQL Lab 或数据库访问权限的用户,可能具备比数据集查询更大的访问范围。因此,生产环境应限制任意 SQL 工具,并优先让 Agent 使用数据集查询接口。

四、开发认证与生产认证必须分开

开发阶段可以配置固定用户,方便调试:

复制代码
MCP_DEV_USERNAME = "admin"

但这种模式下,所有 MCP 请求都会以同一个用户执行,绝对不能直接用于多用户生产环境。

生产环境应启用 JWT,并校验签名、签发者、受众和过期时间:

复制代码
MCP_AUTH_ENABLED = True
MCP_JWT_ISSUER = "https://auth.example.com"
MCP_JWT_AUDIENCE = "superset-mcp"
MCP_JWT_ALGORITHM = "RS256"
MCP_JWKS_URI = "https://auth.example.com/.well-known/jwks.json"

MCP_DEV_USERNAME = None

令牌应使用短有效期,并将用户身份映射到真实的 Superset 用户。自动化任务则使用独立服务账号,授予最小权限,而不是复用 Admin。

五、Redis 缓存配置中的真实问题

图表查询会访问 DATA_CACHE_CONFIG。即使业务数据库测试连接成功,只要 Redis 认证失败,图表接口仍会返回 500。

我们曾遇到过这个错误:

复制代码
redis.exceptions.AuthenticationError:
invalid username-password pair or user is disabled

最终发现部署环境中的 Redis 密码包含了额外引号。推荐统一使用环境变量,并正确编码连接信息:

复制代码
import os
from urllib.parse import quote

REDIS_HOST = os.getenv("REDIS_HOST", "127.0.0.1")
REDIS_PORT = int(os.getenv("REDIS_PORT", "6379"))
REDIS_USER = os.getenv("REDIS_USERNAME", "default")
REDIS_PASSWORD = os.environ["REDIS_PASSWORD"]

password = quote(REDIS_PASSWORD, safe="")
redis_url = (
    f"redis://{REDIS_USER}:{password}"
    f"@{REDIS_HOST}:{REDIS_PORT}/2"
)

DATA_CACHE_CONFIG = {
    "CACHE_TYPE": "RedisCache",
    "CACHE_KEY_PREFIX": "superset_data_",
    "CACHE_REDIS_URL": redis_url,
}

密钥、数据库密码和 Redis 密码都不应写进 superset/config.py,更不能提交到 Git。Superset 官方的生产安全文档也明确建议使用环境变量或密钥管理服务,而不是在配置文件中硬编码。Superset 生产安全文档

六、FastMCP 的模块遮蔽问题

另一个比较隐蔽的问题发生在以下启动方式:

复制代码
cd /home/ubuntu/prod/ai_superset
python superset/app.py

Python 会把脚本所在的 superset/ 目录放到模块搜索路径最前面。Superset 自己存在 superset/key_value/,它可能遮蔽 FastMCP 依赖的第三方 key_value.aio,最终出现:

复制代码
ModuleNotFoundError: No module named 'key_value.aio'
FastMCP server support is not installed

依赖实际上已经安装,问题出在模块搜索顺序。正确方式是从项目根目录按模块或 WSGI 应用启动:

复制代码
python -m superset.app

生产环境则使用:

复制代码
gunicorn \
  --bind 127.0.0.1:9000 \
  --workers 2 \
  --worker-class gthread \
  --threads 8 \
  --timeout 300 \
  "superset.app:create_app()"

Superset 官方同样不建议在生产环境使用 superset run 或 Flask 开发服务器,而应使用 Gunicorn 等 WSGI 服务。Superset 配置文档

七、Nginx 与登录保护

Gunicorn 只监听本机地址:

复制代码
location / {
    proxy_pass http://127.0.0.1:9000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

公开官网和数据应用使用不同域名。官网允许搜索引擎抓取,Superset 应用则保持登录保护,并增加:

复制代码
add_header X-Robots-Tag "noindex, nofollow, noarchive" always;

robots.txtnoindex 只能控制搜索展示,不能代替鉴权。真正的保护仍然是登录状态、RBAC、资源权限、RLS 和接口层的 401/403 响应。

八、AI BI 的能力边界

AI Agent 可以降低查询、筛选和可视化配置的操作成本,但不能自动理解企业所有业务口径。

例如,"销售额"可能代表含税金额、实收金额、订单金额或退款后的净额。即使 SQL 语法完全正确,指标定义仍可能错误。

因此,我们把 AI 的定位设计为:

  • 帮助用户表达分析需求
  • 查找用户有权限的数据集
  • 生成候选分析和可视化
  • 保留查询与图表配置供用户检查
  • 让重要结论经过人工核验

权限控制决定"能不能访问",业务语义决定"分析得对不对",两者缺一不可。

九、总结

将 Superset 改造成 AI BI,最难的部分不是调用大模型,而是让 AI 完整继承现有的数据权限、资源权限和审计边界。

这次实践中最关键的经验是:

  1. Agent 不应直接连接业务数据库。
  2. 每次工具调用都必须绑定真实用户身份。
  3. 数据集、图表和仪表盘必须执行对象级权限检查。
  4. 开发固定用户不能带到生产环境。
  5. Redis、JWT、数据库凭据必须使用环境变量或密钥服务。
  6. AI 输出必须保留可验证的 SQL、数据口径和图表配置。
  7. 公开官网与登录后的数据应用必须分离。

澈析 BI 目前提供智能数据分析、图表与仪表盘、AI Agent 和权限隔离能力。产品介绍与免费试用地址:

澈析 BI - 免费试用的智能 BI 与 AI 数据分析工具

推荐标签:

复制代码
Apache Superset、BI、AI Agent、MCP、数据可视化、
数据权限、Row Level Security、Python、Flask、Gunicorn
相关推荐
fthux3 小时前
“装闭”,让装修套路“装”不下去
人工智能·ai·开源·github·open source
玉鸯4 小时前
Agent Hook:在概率推理之上,为 Agent 叠加确定性控制
python·langchain·agent
doiito5 小时前
【AI 应用】从“外国人味”到地道中文:kokoroi-rs v0.1.2 架构升级深度解析
ai·rust·系统设计
犀利豆5 小时前
多轮对话生成架构图 Agent 设计实践
agent
吴佳浩6 小时前
今天我们讲讲大模型的“核心”技术:蒸馏(Model Distillation)
人工智能·llm·agent
阿里云大数据AI技术6 小时前
阿里云 ES AI 引擎版:面向 Agent 场景,为亿级租户、千亿规模向量设计的搜索引擎
人工智能·elasticsearch·agent
星栈6 小时前
翻完 Pi 源码:它和 Codex、Claude Code 有何不同
人工智能·agent
GPUStack6 小时前
怎么优雅地在GPUStack上使用minerU?
ai·大模型·llm·gpu·vllm·gpu集群·gpustack
码哥字节7 小时前
Google 上周推了个 agents-cli,我装完发现 Claude Code 多了 7 个超能力
google·agent·claude
临床数据科学和人工智能兴趣组8 小时前
RStudio的Console(控制台)是一个非常重要的组件
人工智能·机器学习·数据分析·r语言·r语言-4.2.1