分发给玩家的游戏需要发送遥测的权限,构建比较任务需要读取数据的权限。两者共用一个凭据,就可能让人从游戏安装包中提取出分析数据的访问权限。
在 Framedash 中,游戏使用 Ingest 密钥,常规分析使用另一个 Read-only 密钥。两种密钥都以 fd_ 开头。服务端根据密钥中保存的 scope(允许执行的操作集合)进行授权,密钥名称和前缀并不能决定权限。
按操作选择预设
项目控制台的 API 密钥页面提供以下预设。各预设的 scope 组合见 API 概述。
| 预设 | 保存的 scope | 用途 |
|---|---|---|
| Ingest | events:write | 发送 SDK 遥测 |
| Read-only | analytics:read | 读取聚合数据、项目状态和配置,比较构建 |
| Read & Write | analytics:read, resources:write | 在读取之外,修改地图、内容和告警 |
| Full | analytics:read, resources:write, data:admin | 进一步执行原始 SQL、导出数据和删除玩家遥测 |
Full 不包含 events:write。 它不能代替游戏使用的 Ingest 密钥。这些预设是不同操作权限的组合,并不是高一级就包含低一级全部操作的阶梯关系。
使用原始 SQL 时,尤其要留意授予的权限。即使是 SELECT,也能返回玩家级别的行,因此 /api/v1/query 要求 data:admin。这个 scope 同时允许导出和删除玩家数据。为了运行一条查询而选择 Full,也会授予另外两种操作的权限。如果聚合 API 已能回答问题,就优先使用它;更广的权限只交给确实需要它的受控进程。
密钥绑定到一个项目。传入其他项目 ID,并不会得到该项目的访问权限。拥有 scope 也不能绕过账户限制或请求速率限制。
不把分析凭据放进分发构建
图中上方的路径将 SDK 事件发送到 https://ingest.framedash.dev/v1/events,下方的读取路径使用 https://app.framedash.dev/api/v1。分析凭据应保存在受控的开发机器、后端或可信 CI 运行器上。不要将它们放进游戏资源、Web 游戏的 JavaScript、可下载的配置或公开的构建产物。
应按“可以被提取”来对待分发到客户端的密钥。把值从源代码移到构建时环境变量,可以让它不再出现在那份源文件中;但如果构建过程把它复制进最终安装包,它仍然不保密。不要因为做了混淆,就分发权限更高的密钥。OWASP 关于应用包内敏感数据的说明也讨论了这种提取风险。
做性能检查时,游戏进程需要 Ingest 密钥,负责比较的 CLI 需要 Read-only 密钥。只把凭据交给需要它的进程。CLI 的 --api-key-file 选项可以从私有文件读取密钥,避免将密钥值放在命令行参数中。但能访问同一台机器或工作区文件的代码,仍然可能读到这个文件。
Ingest 密钥暴露后仍能做什么
Ingest 密钥不能读取分析数据、修改地图或删除已有的玩家遥测,但它可以向所属项目提交事件。提取到密钥的人,可以在采集服务接受的格式和限制范围内发送伪造遥测。
这些事件可能污染测量结果,也可能占用采集处理能力或事件额度。API 密钥验证的是发送凭据所具备的权限,无法证明某个帧时间样本来自未经修改的游戏,也无法证明申报的玩家 ID 或构建 ID 真实。仅授予采集写入权限,不能阻止伪造事件。
用于发布决策的受控测试数据,应尽可能与公开客户端的遥测分开。需要隔离时,可以使用不同项目。只换一个由客户端填写的构建 ID,不等于验证了数据来源。出现异常增长时,应与自己的运行器记录核对。如果威胁模型要求更严格的来源验证,就需要在自己控制的后端设计验证流程;仅靠密钥分离无法提供这种验证。
限制 CI 和智能体的访问范围
接收 CI secret 的代码可以使用它。不要在能读取分析或管理密钥的任务中运行不可信拉取请求里的代码。GitHub 的安全使用指南介绍了不可信代码检出、脚本注入和日志脱敏的局限。应审查工作流变更,将具有权限的分析任务与不可信构建分开。
给分析智能体配置凭据时,先从 analytics:read 和调查必需的工具开始。遥测文本、仓库文件和工具结果都应视为不可信输入。其中出现的指令,不应成为访问秘密信息、转发凭据或扩大 scope 的授权依据。不要把密钥粘贴到提示词或工具输出中。
最小权限可以限制一次错误工具调用所能执行的操作。不过,Read-only 密钥仍能读取项目信息,因此还要控制智能体可以把结果发送到哪里。“不要修改数据”这样的提示词,不能代替服务端强制执行的 scope 限制。
不发送测试事件也能验证密钥
GET https://app.framedash.dev/api/v1/whoami 通过 X-API-Key 验证 API 密钥,Ingest 密钥也适用。不必为了确认密钥而上传遥测。这个端点只接受 API 密钥,不接受 OAuth Bearer 令牌。
下面的 Python 脚本从秘密管理工具提供给该进程的环境变量中读取密钥,不将其放进命令行参数,也不打印密钥值。运行时不要开启环境变量转储或调试日志。
import json
import os
import urllib.request
request = urllib.request.Request(
"https://app.framedash.dev/api/v1/whoami",
)
request.add_unredirected_header("X-API-Key", os.environ["FRAMEDASH_API_KEY"])
with urllib.request.urlopen(request, timeout=15) as response:
data = json.load(response)["data"]
print(json.dumps({"projectId": data["projectId"], "scopes": data["scopes"]}))
检查返回的项目 ID 和 scope 是否符合该任务的用途。仅限 Ingest 的密钥会返回 projectId 和 scopes,具有分析或管理 scope 的密钥会收到额外元数据。无效或已撤销的密钥返回 401;账户限制和请求速率限制等检查也可能拒绝请求。验证成功只能确认密钥当前绑定的项目和权限,不能确认已采集数据的完整性或真实性。
下次发布前,检查游戏安装包和 CI 凭据配置。如果分析密钥进入了公开产物,应撤销它,在受控使用方替换新密钥,并移除暴露的副本。已经分发的 Ingest 密钥则需要结合客户端更新安排更换:撤销旧密钥,也会让仍使用它的客户端停止上报遥测。记录每个构建或任务使用的密钥,才能在事故发生前看清更换的影响。