
一、为什么 Serverless 让传统凭据体系失灵函数计算FaaS的核心特征是无状态、无长驻、按调用计费。一个函数实例在收到请求时被平台拉起执行完即被回收或挂起下一次请求可能落在全新实例上。这种模型对凭据管理提出了三个传统架构从没认真面对过的约束。第一没有地方放连接池。传统应用启动后在内存里维护一个数据库连接池凭据只在进程启动时加载一次之后所有请求复用同一条长连接。函数实例可能在毫秒级被创建也可能被平台复用但你无法保证上一秒的实例还在、连接池还在。把连接池塞进函数入口并不现实——实例被回收时连接随之丢失下一次冷启动又要重建。第二长生命周期凭据的风险被放大。如果函数代码里硬编码了一个数据库密码而这个密码 90 天不换那么任何一个被部署到公网、或镜像被上传到制品库的函数版本都是一个长期暴露面。函数代码天然分散在大量小仓库里凭据散落的概率远高于单体应用。一旦某个函数镜像流入公共制品库硬编码的密码就永久泄露。第三调用之间的最小授权难以落地。A 调用只需要读一张表B 调用需要写另一张表但函数拿到的往往是一把万能钥匙——一个拥有整库权限的账号。在 FaaS 场景下一个函数 一个身份的粗放划分让越权操作与凭据滥用几乎无法在凭据层面被拦截。这就引出一个核心命题函数计算需要的是短时凭据——按调用维度发放、用完即销毁、带 TTL 的临时凭证而不是一份写死在环境变量里的长期密码。把长期密码塞进无状态函数本质上是用有状态的安全假设去套无状态的运行模型模型错配必然漏水。很多团队的第一反应是那我把密码放进环境变量总可以了吧。环境变量比硬编码好一点但它仍然是长期凭据——它跟着函数版本走版本不更新密码就不变而且环境变量在运行时对函数代码完全可见日志打印、错误堆栈、依赖库的上报行为都可能把它带出去。环境变量只是把明文从代码挪到了配置并没有改变凭据长生不老、权限一给到底的本质。要从根上解决必须换一种凭据形态这正是下一节要讲的短时凭据供给模型。二、短时凭据的供给模型短时凭据与传统静态凭据的本质区别在于凭据的生命周期绑定对象不同。静态凭据的生命周期绑定配置你改一次配置、重启一次服务它才变化短时凭据的生命周期绑定调用或会话发放即开始倒计时到点或调用结束即失效。维度静态长期凭据动态短时凭据生命周期锚点与配置文件绑定与调用 / 会话绑定授权粒度通常整库、整桶权限可细化到表、前缀、操作泄露半径泄露后长期有效检测窗口以月计TTL 到点自动失效窗口以分钟计轮换成本改配置 重启服务无需运维介入自动过期越权拦截依赖应用自身逻辑凭据本身携带策略强制适用场景长驻有状态服务函数、临时任务、CI、批处理短时凭据要真正起作用必须守住三条纪律少一条都会退化回静态凭据的处境最小授权。每次调用只申请本次操作必需的权限不超额。一个只读报表函数绝不该拿到 DELETE 权限即便数据库账号本身支持。用完即销。函数执行结束无论成功或异常或凭据 TTL 到期凭据立即作废不能再用于下一次调用。残留凭据是传统架构最常见的隐患来源短时凭据通过生命周期把这一隐患直接消除。TTL 硬约束。凭据有效期从秒级到分钟级由系统强制而非靠约定。即便凭据在传输途中被截获攻击者能用的窗口也极短且凭据与具体调用绑定难以挪作他用。值得强调的是最小授权和 TTL 必须同时存在。只有最小授权没有 TTL凭据仍可能被长期持有只有 TTL 没有最小授权攻击者拿到凭据后依然能做超额操作。两者叠加才构成函数场景下的安全闭环。三、冷启动密钥注入的时序方案冷启动指函数实例从不存在到可执行的过程。若每次冷启动都向凭据管理系统同步申请一份动态凭据会引入额外网络往返。下面给出注入时序的伪代码核心是把凭据的申请—使用—吊销严格收敛在一次调用边界内。// 冷启动密钥注入时序伪代码平台无关 func handler(event): // 1. 从函数运行环境的安全上下文读取临时函数角色身份 // 该身份由平台注入非长期密钥仅用于向凭据服务鉴权 roleToken env.get(FUNCTION_ROLE_TOKEN) // 2. 用函数角色向凭据服务申请短时凭据 // 携带 TTL 与本次调用所需的最小权限范围 cred smsClient.issueCredential( role roleToken, scope event.requiredScope, // 例如 db:orders:read ttl 300, // 秒短于函数最大执行时长 bindIp currentRuntimeIp // 可选绑定运行实例防凭据被挪走 ) // 3. 用短时凭据建立数据库连接仅本次调用有效 conn db.connect(cred.username, cred.password, cred.host) // 4. 执行业务逻辑 result process(event, conn) // 5. 函数返回前主动吊销确保用完即销 // 即使吊销请求失败TTL 也会兜底失效 smsClient.revoke(cred.id) conn.close() return result // 异常路径同样要吊销用 defer / finally 兜底 func handlerSafe(event): cred issueCredential(...) try: return processWith(event, cred) finally: smsClient.revoke(cred.id) // 异常也不留残留凭据这段伪代码里有几个工程上不能省略的细节。其一角色身份FUNCTION_ROLE_TOKEN是平台注入的临时令牌不是业务长期密钥它本身也带有效期用于向凭据服务证明我是哪个函数再由凭据服务根据角色策略换算出真正的数据源凭据。其二第 5 步的吊销必须有finally兜底否则函数抛异常时凭据会残留到 TTL 到期期间仍有被复用的风险。其三吊销失败不能阻塞主流程TTL 是最后一道兜底——这也是硬约束的含义不依赖任何人为操作到点必失效。四、冷启动延迟优化如果每次调用都走完整申请—使用—吊销流程冷启动 P99 可能多出 50–150ms 的凭据往返开销。对延迟敏感的函数需要分层优化。4.1 凭据缓存调用级而非实例级函数实例若被平台复用warm 实例可在实例内存缓存凭据直至 TTL 临界避免重复申请。但缓存必须绑定到实例生命周期实例回收即清空绝不能落盘到函数镜像或共享存储。缓存策略命中率额外延迟收益风险与适用每次调用都申请无缓存无最安全延迟最高的场景可用实例内缓存至 TTL高省去重复申请往返需防跨调用越权缓存键要带 scope全局共享缓存高省去大量申请越权风险大不推荐用于函数要点是缓存键必须带scope。同一个 warm 实例处理读订单和写物流两个不同调用时绝不能复用同一份凭据否则最小授权被破坏。缓存应做到同 scope 命中、异 scope 重新申请。4.2 连接复用把数据库连接从每次新建改为实例级连接句柄复用凭据只在连接建立时消费一次后续调用复用同一条连接。这要求凭据 TTL 长于实例预期存活时间否则连接中途因凭据失效而断。实践上可以为 warm 实例维护一个轻量连接句柄池连接建立时用短时凭据鉴权之后复用。实例挂起或回收时连接池整体释放凭据随之作废。这样既享受了连接复用的吞吐又不破坏用完即销的纪律。4.3 实例预热对延迟敏感的函数设置最小实例数provisioned concurrency预先完成冷启动与首次凭据注入使真实流量直接命中 warm 实例。预热实例在空闲期也可以周期性地空跑一次注入流程保持凭据与连接的新鲜度避免首个真实请求撞上冷启动。预热的代价是常驻实例带来的成本上升因此不是所有函数都该预热。一个实用的判断标准是把函数按延迟敏感度 × 调用频次划分。高频且敏感的核心链路如交易回调、实时风控值得预热低频或离线批处理类函数则放任冷启动即可多出的百毫秒延迟无关紧要。预热实例同样要遵守 TTL 纪律——即便常驻凭据也不能无限期持有预热时签发的凭据到期后要随连接一起刷新不能因为实例一直活着就跳过轮换。优化手段主要收益代价适用函数凭据缓存降低重复申请延迟需严格按 scope 隔离高频、同 scope 调用连接复用降低建连延迟凭据 TTL 需更长IO 密集、长事务实例预热消除冷启动本身常驻成本上升延迟敏感、核心链路以安当SMS为例凭据发放接口支持按函数角色维度签发带 TTL 的动态凭据函数侧只需在入口处做一次角色校验、在出口处触发吊销凭据的最小授权范围可在控制台按函数—数据源维度配置业务代码无需改动。国密 SM4 被用于凭据的存储加密根密钥托管在 HSM 中函数侧拿到的始终是已加密通道下发放的明文临时凭据镜像与日志里不会出现任何长期密钥。五、与 K8s 动态凭据的对比K8s 环境有 Sidecar 或准入控制器常驻可在 Pod 创建时注入动态凭据并定期轮换FaaS 没有常驻代理必须靠函数自身在运行期主动拉取。两者底层可接入同一套凭据管理系统差异集中在谁触发发放与凭据生命周期锚点。对比项K8s 动态凭据函数计算短时凭据注入时机Pod 启动常驻代理完成调用开始函数内主动拉取轮换方式Sidecar 定期静默轮换调用结束即吊销下次重发连接池可用长连接稳定受限依赖实例级复用最小授权按 Pod / ServiceAccount按调用 / 角色更细冷启动影响无代理随 Pod 常驻需优化注入延迟残留凭据风险中Pod 销毁才清低TTL 吊销双保险可以看到函数计算的短时凭据在最小授权和残留风险两项上反而优于 K8s 常驻模式因为它把凭据生命周期压到了单次调用。代价是冷启动延迟需要专门优化这正是第四节的内容。对已经在使用 K8s 动态凭据的团队向 FaaS 迁移时最大的认知转变是不要再试图给函数一个长期身份而是给每次调用一个临时身份。中间件接入方式也一脉相承——Spring Boot 应用接入只需引入 Starter 并改动不超过 5 行配置即可获取动态凭据K8s 通过 Sidecar 拉取短时凭据函数计算则在入口处主动签发三者共享同一套凭据治理策略。迁移过程中常见的两个坑值得单独说。第一不要因为函数偶尔被复用 warm 实例就认为缓存的凭据可以跨调用共享。warm 实例的复用是平台行为不可预测凭据缓存必须严格以 scope 为键宁可多申请一次不可越权一次。第二不要把 K8s 里长连接常驻的习惯带进函数。函数实例随时可能被回收任何写在全局变量里的长连接都可能在下一次调用时变成僵尸连接正确做法是把连接句柄也视为随实例生命周期的对象与凭据一起在实例挂起时整体释放。理解了这两点从 K8s 到 FaaS 的凭据模型切换就只是接口形态的变化而非安全等级的妥协。六、密钥托管与审计短时凭据不会凭空安全短时凭据之所以安全不只是因为短更因为发放它的那套系统本身可信。如果凭据服务自己把主密钥明文放在磁盘上或者发放记录不可追溯那么再短的 TTL 也救不了底层的信任崩塌。函数场景把凭据拉到了调用边界反而更依赖底层密钥托管与审计能力。根密钥不应与业务同机共存。合理的做法是把根密钥托管在 HSM硬件安全模块中所有动态凭据的派生与加解密都在 HSM 内完成业务侧即便被攻破也拿不到根密钥。存储层的凭据落库时要用国密算法如 SM4加密内存里的临时明文只在发放瞬间与函数运行期存在不进日志、不落盘。审计链路同样关键。每一个函数的每一次凭据申请、吊销、越权拦截都要有结构化记录谁哪个函数角色、什么时间、申请了什么范围、是否成功、何时失效。这些记录不是给运维看热闹的而是合规举证的硬证据——当审计方问这个函数上周三凌晨是否越权访问过用户表你要能用一条带时间戳和策略 ID 的日志回答而不是翻代码去猜。特别要区分凭据自动轮换与短时凭据的关系。前者解决的是长期凭据长生不老的问题属于被动兜底后者把凭据生命周期压到调用级属于主动收敛。两者并不互斥即便基础数据源账号靠自动轮换保持新鲜函数侧仍应申请短时凭据因为轮换的周期通常是小时或天远大于单次调用的安全窗口只有短时凭据才能把单次暴露面压到最小。七、落地场景短时凭据不是实验室里的概念它真正发挥价值的地方是那些函数要碰敏感数据的高频场景。下面三个场景覆盖了绝大多数函数计算的数据访问诉求也是凭据泄露最容易发生的地方。6.1 云函数访问 RDS / 数据库数据面函数需要读业务库做轻量聚合。传统做法把数据库密码写进函数环境变量一旦函数代码仓库或镜像泄露即泄露。改为函数入口申请只读、TTL 5 分钟的短时凭据业务代码零改动凭据绝不落盘。支持的数据库类型覆盖 MySQL、PostgreSQL、Oracle、SQL Server、Redis以及国产数据库达梦、人大金仓。函数访问这些数据源时凭据发放逻辑完全一致只是连接串不同迁移成本低。6.2 云函数访问对象存储文件处理类函数如缩略图生成、文档转码需临时读写对象存储桶。用短时凭据签发仅本桶、仅本次任务前缀的临时 token任务结束自动失效避免一个函数拥有整桶长期写权限。6.3 跨云 / 多云函数调用消费品企业在多家云上运行函数凭据散落在各云自带的密钥服务里难以统一审计与轮换。集中式凭据管理系统统一发放与吊销函数侧只认一个角色身份无论跑在哪朵云凭据策略与审计口径一致。某三甲医院将密钥管理与凭据管理结合凭据泄露面下降 90%新系统开通从 2 小时缩至 5 分钟某消费品多云客户将凭据轮换从 3 天压到 5 分钟。这些案例说明短时凭据在 Serverless 场景下能直接转化为运维效率与安全水位双重收益而不是增加负担。八、工程落地 checklist函数镜像与配置中不得出现任何长期凭据凭据只来自运行期注入。凭据 TTL 必须短于函数最大执行时长留出安全余量避免连接中途断掉。出口务必用finally吊销避免函数异常时凭据残留到 TTL。角色权限按最小授权配置一个角色不应通吃所有数据源。缓存凭据时必须带 scope 键杜绝跨调用越权复用。对延迟敏感路径启用实例预热与连接复用把注入延迟控制在基线内。用统一审计日志观察每个函数实际申请的凭据范围定期收敛超额权限。方案参考落地函数计算短时凭据供给时建议先从数据源分类做起把函数要访问的数据库、对象存储、消息队列逐一登记明确每个数据源的最小权限集合。其次建立函数—角色—权限三级映射让每次调用只拿必需权限而不是给函数一个通吃账号。第三在 CI 阶段把凭据申请与吊销写成可复用的包装层例如一个函数中间件或装饰器业务代码保持纯净安全逻辑集中在边界。第四用统一审计日志观察每个函数实际申请的凭据范围与频次定期把超额权限收敛下来避免权限随业务演进悄悄膨胀。最后对延迟敏感函数做冷启动基线测量结合凭据缓存与实例预热把注入延迟控制在可接受区间再决定是否引入连接复用。整体思路是凭据跟着调用走、权限按动作切、生命周期有硬约束而非把长期密码塞进无状态的函数里——前者把安全建在运行模型本身后者只是把隐患搬到更难排查的地方。