描述“连接池复用”在多租户下的安全风险。

解读

在国内公有云或金融云场景里,一个 Cloud SQL 实例常被多个业务线(租户)共用,以节省成本。连接池(HikariCP、Druid、Spring 默认池)会把物理连接缓存下来反复使用,只要 TCP 不断、会话变量未重置,下一次复用就仍带着上一次的上下文。如果池层不做“租户级隔离”,就会出现 A 租户残留的 Session 变量、临时表、角色、SET 指令甚至 cursor 状态被 B 租户直接继承,导致越权、数据污染或审计轨迹错乱。面试官想听的是:你能否把“连接复用”与“多租户”这两个维度叠加,把风险场景、攻击路径、Google Cloud SQL 的缓解机制都说清楚。

知识点

  1. 租户隔离模型:国内常见“共享实例+独立库/schema”模式,IAM 只到实例级,库内仍靠自建用户体系。
  2. MySQL 会话污染SET @user_id = 10086 这类用户变量在连接归还后不会自动清零;SQL SECURITY DEFINER 的临时存储过程也可留在内存。
  3. PostgreSQL 会话污染SET SESSION AUTHORIZATIONSET roleSET search_path 会一直保持到显式 RESET 或连接关闭;临时表 ON COMMIT PRESERVE ROWS 跨事务存活。
  4. Cloud SQL 自带机制
    • Cloud SQL Auth Proxy 的 IAM 鉴权每次走 OAuth2 令牌,令牌换人不复用同一物理连接,天然阻断跨租户复用。
    • 私有 IP + 自建池时,Google 不再做会话级重置,风险落到应用侧。
  5. 国内合规:《个人信息保护法》第 38 条要求“采取必要措施确保境外接收方处理活动达到本法保护水平”,若池复用导致日志错位,审计失效即视为违规

答案

在 Cloud SQL 多租户场景下,连接池复用带来的核心风险是**“会话上下文残留导致横向越权”**。
具体表现三步走:
身份残留:A 租户业务通过 SET SESSION AUTHORIZATIONSET role 提升为 rdsAdmin 后归还连接,池未重置,B 租户拿到同一连接即拥有管理员权限。
数据残留:A 租户创建的 ON COMMIT PRESERVE ROWS 临时表或 MySQL 用户变量仍可见,B 租户可直接 SELECT 到上一租户的敏感中间结果。
审计错位:Cloud SQL 的 pgAudit 或 MySQL Audit Plugin 以“连接 ID”为线索,若连接 ID 复用,监管部门看到的日志主体将错误地指向最后一个复用者,导致溯源失败,违反等保 2.0 对审计完整性的要求

缓解手段:

  1. 优先使用 Cloud SQL Auth Proxy,每次新令牌强制建立新连接,彻底避免复用
  2. 若必须用私有 IP+自建池,在归还连接前显式执行“会话重置脚本”
    • MySQL:RESET SESSION VARIABLES; DROP TEMPORARY TABLES;
    • PostgreSQL:RESET ALL; SET SESSION AUTHORIZATION DEFAULT; CLOSE ALL;
  3. 按租户拆池,最小化连接混用;
  4. 打开 Cloud SQL 的 cloudaudit.googleapis.com/data_access 日志,并在应用侧把租户 ID 注入到 application_name实现双层审计对齐

拓展思考

面试官可能追问:“如果租户量级达到万级,拆池会耗尽实例连接上限,怎么办?”
可答:

  • 采用 “分池+令牌桶”混合模式:把租户哈希到 64 个池,每个池上限 20 连接,用 Guava RateLimiter 做二次流控,既控制总连接数,又把同一租户尽可能落到同一池,降低交叉概率
  • 利用 Cloud SQL 新推出的“Pooler”预览版(基于 PgBouncer 改造),支持 “事务级重置”,每次事务结束自动 DISCARD ALL比应用层重置更轻量
  • 最终架构:Proxy 池负责“身份隔离”,Cloud SQL Pooler 负责“会话隔离”,两层叠加可在万租户场景下把越权风险降到 <0.01%,同时保持 QPS 提升 30% 的运维收益。