先看结论与判断条件
- RACI 中每个关键活动应有唯一 Accountable,Responsible 可以多人,但必须明确谁实际产出工件和回执。
- 研发负责可构建输入、业务边界和缺陷修复,安全团队负责威胁模型、保护规则和证据门禁,两者不能互相代签。
- 供应商可以执行加固、输出技术报告和支持定位,但不应默认保管客户生产私钥或批准业务风险例外。
- 发布团队负责生产签名身份、release 变体、商店或企业分发与回滚入口,上传动作不是完整发布责任。
- 兼容验收必须由了解业务路径的客户角色批准,供应商自测可作为证据,不能单独替代买方接受。
- 事故响应要预先指定候选冻结、证据保全、密钥处置、技术定位、业务通告和回滚决策,不能故障发生后临时找人。
先统一 R、A、C、I 的含义
RACI 不是把所有团队名称填进表格。Responsible 表示实际执行并交付工件的人,Accountable 表示对活动结果作最终批准且承担结果的人,Consulted 在决策前提供必要意见,Informed 在结果形成后获得通知。最常见错误是一个活动有多个 A,出现问题时每个人都以为别人批准。
每个关键活动应只有一个 A,至少一个 R。A 可以兼任 R,但在生产签名、正式发布和风险例外等高影响活动中,应检查是否形成不受复核的单人闭环。C 和 I 不应无限扩张;被咨询者要有明确输入,被知会者只接收结果,不承担隐含审批。
矩阵以活动和交付物为粒度,而不是以项目阶段为粒度。写研发负责开发、安全负责安全、供应商负责加固没有可执行性。应写谁生成可复现输入包、谁批准保护规则、谁核对输出摘要、谁执行设备测试、谁批准例外、谁控制签名和谁点击最终发布。矩阵旁还要写出每项活动的输入、输出、完成标准和替补角色;主责人员离岗时,替补必须通过明确授权接管,不能把无人响应误当作默认批准。
| 角色码 | 含义 | 必须产出 | 常见误用 |
|---|---|---|---|
| R | 执行活动 | 工件和执行回执 | 写团队名却无人动手 |
| A | 最终批准结果 | 批准记录和接受边界 | 多个批准人互相等待 |
| C | 决策前提供意见 | 评审意见或约束 | 被当作共同批准 |
| I | 结果后获得通知 | 通知回执 | 被要求承担结果 |
| Exception owner | 接受已知风险 | 范围与到期时间 | 交给执行供应商 |
| Artifact owner | 维护候选身份 | 摘要与版本链 | 只记录文件名 |
输入构建和样本交接由研发主责
研发团队应负责生成可复现的 release 输入,固定源码版本、依赖锁、构建工具、变体、ABI、资源和服务端环境要求。交给供应商的 APK、AAB、IPA 或 SO 必须记录摘要、版本、签名状态和公开业务检查清单,避免供应商处理了错误样本后才发现。
SLSA Provenance v1.1 将产物 subject、构建者、构建类型、外部参数和依赖材料组织进构建证明。研发或内部构建平台负责提供输入 provenance;供应商只能为自己的处理步骤生成后续 lineage,不能替代客户解释原始代码和依赖如何构建。
样本交接要定义传输渠道、访问权限、保留期、删除回执和敏感信息清单。供应商作为 R 接收并校验摘要,研发或制品负责人作为 A 确认输入身份。若摘要不一致,流程立即停止,不允许凭文件名或版本号继续。
| 活动 | R | A | 主要工件 |
|---|---|---|---|
| release 输入构建 | 研发或构建平台 | 研发负责人 | 输入包与 provenance |
| 依赖与变体固定 | 研发 | 研发负责人 | 锁文件和构建配置 |
| 样本摘要登记 | 制品管理员 | 研发负责人 | 摘要与版本记录 |
| 安全传输 | 制品管理员与供应商 | 项目负责人 | 交接回执 |
| 供应商接收校验 | 供应商 | 制品负责人 | 接收摘要 |
| 样本删除 | 供应商 | 项目负责人 | 删除或保留证明 |
保护规则由安全牵头,业务边界由研发确认
安全团队负责威胁模型、保护目标、禁止项和证据门禁,供应商负责把规则映射到工具配置并说明限制。研发必须确认反射、序列化、JNI、动态加载、热修复和第三方 SDK 等业务边界,因为只有研发知道哪些名称、入口和生命周期不能随意变换。
保护范围审批不能只由供应商完成。供应商可以建议哪些函数适合虚拟化、混淆或完整性检查,但客户安全负责人应作为 A 批准策略,研发作为 C 确认兼容边界。任何因兼容问题移除保护的决定,都要回到同一负责人审批并记录影响。规则评审回执应列出候选版本、配置摘要、变更原因和反对意见处理,避免会议结论在工具配置中被重新解释。
in-toto Attestation Statement v1 可以把产物 subject 与有类型的声明负载绑定。供应商输出配置证明或处理 attestation 时,应绑定输入输出摘要、predicate 类型和签发身份。安全团队负责验证声明结构和信任策略,不能只看报告页面显示成功。
| 活动 | 负责执行 R | 最终批准 A | 咨询 C |
|---|---|---|---|
| 威胁模型 | 安全团队 | 安全负责人 | 研发与业务 |
| 保护对象清单 | 安全与供应商 | 安全负责人 | 研发 |
| 反射与 JNI 边界 | 研发 | 研发负责人 | 供应商与安全 |
| 工具配置生成 | 供应商 | 安全负责人 | 研发 |
| 配置例外 | 安全团队 | 风险负责人 | 研发与供应商 |
| 处理 attestation | 供应商 | 安全负责人 | 制品管理员 |
生产签名密钥不能落入模糊责任区
Sign your Android app 说明发布要区分应用签名密钥、上传密钥、证书和 Play App Signing 责任。矩阵必须写清加固前样本是否已签名、处理是否移除签名、输出由谁签名、使用哪个受控系统以及谁验证证书身份。不能简单写供应商负责签名。
生产私钥原则上由客户的密钥管理和发布体系控制,供应商接收未签名输出或使用受限测试身份完成技术验证。若业务确需委托签名,应建立明确授权、HSM 或等价控制、最小访问、双人审批、审计和撤销安排,不能通过聊天或普通文件传递密钥。密钥接触面还应覆盖备份、灾难恢复、轮换、离职交接和日志访问;任何导出或临时授权都要有发起人、批准人、用途、候选范围和失效时间,测试密钥也不得被误标成生产签名身份。
Apple app code signing process 说明 Apple 平台通过证书、代码签名和运行验证建立应用身份。iOS 的证书、provisioning、entitlements 和重签责任应单独列出,不能与 Android 上传密钥和 APK 签名方案合并成一格。平台差异是职责输入,不是供应商自行决定的细节。
| 活动 | 建议 A | 允许的 R | 禁止默认 |
|---|---|---|---|
| 生产密钥托管 | 客户密钥负责人 | 客户受控系统 | 供应商普通存储 |
| Android 上传签名 | 发布负责人 | 受控发布流水线 | 个人本地签名 |
| Play App Signing 配置 | 发布负责人 | 商店管理员 | 供应商代管账号 |
| Apple 证书与 profile | iOS 发布负责人 | 客户签名系统 | 与 Android 混用 |
| 测试包签名 | 测试负责人 | 测试流水线 | 冒充生产身份 |
| 验签回执 | 发布负责人 | 安全或发布工程师 | 只看安装成功 |
兼容测试由供应商执行一部分,客户批准结果
供应商最适合执行工具级静态检查、通用启动冒烟、符号与签名检查,并提供处理前后差异。客户测试团队掌握真实账号、数据、设备和业务路径,应负责核心功能、异常、升级、多进程、后台与性能回归。两边结果都绑定相同候选摘要。
最终兼容接受不能由供应商单独批准。供应商自测回答工具和通用路径是否正常,客户测试回答产品场景是否符合发布标准。测试负责人作为 A 汇总通过、失败、阻塞和未覆盖项,安全与研发提供 C,发布团队根据批准回执决定是否进入签名和发布。
失败归属不应提前固定为研发或供应商。先复现并固定候选,再由研发、供应商和安全共同定位到业务缺陷、加固配置、工具实现、平台行为或测试环境。根因确认后,实际责任方成为修复 R;测试负责人仍负责关闭回归回执。
| 测试 | 供应商 | 客户测试 | 批准人 |
|---|---|---|---|
| 静态结构检查 | 主要执行 | 抽查 | 安全负责人 |
| 通用启动冒烟 | 主要执行 | 复核 | 测试负责人 |
| 核心业务路径 | 支持定位 | 主要执行 | 测试负责人 |
| 设备与系统矩阵 | 提供建议 | 按用户范围执行 | 测试负责人 |
| 性能对照 | 提供工具级数据 | 建立业务基线 | 性能负责人 |
| 失败关闭 | 修复或解释 | 验证修复 | 测试负责人 |
风险例外必须由业务风险负责人批准
保护范围缩减、设备未覆盖、性能门槛未满足或诊断能力受限,都可能形成风险例外。提出例外的人可以是研发、安全、测试或供应商,但 A 必须是有权接受业务影响的客户负责人。供应商不能一边产生限制,一边代表客户批准接受。
例外记录包含候选与配置摘要、问题、影响、已完成证据、替代控制、受影响范围、到期时间、退出条件和责任人。例外只对指定候选和时间有效;版本、配置或平台发生关键变化时重新评审。永久接受和没有影响都不是可审计描述。批准回执还应指定复查日期和关闭证据,例外到期后若没有续批,发布门禁应恢复为阻塞,不能因历史版本曾获批准而自动延长。
NIST SP 800-218 SSDF 强调把来源、构建、验证和变更证据纳入开发流程。例外也是变更证据的一部分,应与后续修复、复测和发布关联。项目经理可以负责催办,不能替代安全或业务风险负责人签署技术与商业接受。
正式发布由客户发布团队控制
Android publish your app 说明发布前要配置 release 变体、构建签名产物、完成测试并准备应用依赖的服务,上传只是其中一步。发布团队应作为正式发布的 A,核对批准候选摘要、签名身份、商店元数据、服务端兼容、灰度、监控和回滚入口。
供应商可以提供未签名加固产物、签名兼容说明和上线支持,但不应默认拥有客户商店账号或最终发布权限。研发负责服务端和客户端版本兼容,安全核对保护与证据,测试提供接受回执;发布负责人确认所有门禁指向同一最终签名候选后执行上传。上传前清单还应逐项记录门禁回执摘要和批准时间,防止审批对象在排队或人工转存期间被替换。
若商店处理、重新签名或拆分分发产生新的交付形态,应记录商店或渠道责任与可取得的最终证据。通用发布指南不能证明某个包符合具体商店政策,政策审核和地区要求应由发布或合规角色单独负责。
| 关口 | R | A | 输入回执 |
|---|---|---|---|
| 候选冻结 | 制品管理员 | 发布负责人 | 最终摘要 |
| 生产签名 | 签名流水线 | 密钥或发布负责人 | 验签结果 |
| 测试接受 | 测试团队 | 测试负责人 | 范围与缺口 |
| 安全接受 | 安全团队 | 安全负责人 | 保护与例外 |
| 商店上传 | 发布工程师 | 发布负责人 | 审批和元数据 |
| 灰度与回滚 | 发布与运维 | 发布负责人 | 监控和回滚条件 |
用校验脚本发现 RACI 缺口和职责冲突
下面的 Python 脚本读取 JSON RACI,要求每个 activity 包含非空的 R、唯一 A、可选 C 和 I。它拒绝重复活动、角色同时出现在 A 与 C 或 I、生产签名由 vendor 执行或批准,以及同一批准人同时控制生产签名和正式发布却没有 approved_exception。
职责分离规则不是说小团队绝对不能兼任,而是要求高影响闭环被显式发现并审批。若组织规模有限,approved_exception 应指向风险记录、复核人和到期时间,生产实现还需验证这些字段。示例只验证结构,不访问人员目录、密钥、商店账号或内部系统。
矩阵变更应走代码评审或等价审批,并绑定项目版本。脚本失败时只调整冲突活动,不重写整个矩阵。通过仅证明角色结构满足规则,不证明被指派人员已完成工件,也不证明产物兼容、安全或成功发布。
import json
import sys
from pathlib import Path
if len(sys.argv) != 2:
raise SystemExit('usage: validate_raci.py raci.json')
input_path = Path(sys.argv[1])
if not input_path.is_file():
raise SystemExit('RACI file is missing')
data = json.loads(input_path.read_text(encoding='utf-8'))
activities = data.get('activities')
if not isinstance(activities, list) or not activities:
raise SystemExit('activities array is missing')
seen = set()
accountable = {}
for index, item in enumerate(activities):
name = str(item.get('activity', '')).strip()
if not name or name in seen:
raise SystemExit(f'invalid activity at index {index}')
seen.add(name)
assignments = {}
for code in ('R', 'A', 'C', 'I'):
values = item.get(code, [])
if not isinstance(values, list) or any(not isinstance(value, str) or not value.strip() for value in values):
raise SystemExit(f'{name}: invalid {code} assignments')
assignments[code] = set(values)
if not assignments['R']:
raise SystemExit(f'{name}: no responsible role')
if len(assignments['A']) != 1:
raise SystemExit(f'{name}: accountable role must be unique')
if assignments['A'] & (assignments['C'] | assignments['I']):
raise SystemExit(f'{name}: accountable role is duplicated in C or I')
accountable[name] = next(iter(assignments['A']))
if name == 'production-signing' and 'vendor' in (assignments['R'] | assignments['A']):
raise SystemExit('production signing is assigned to vendor')
required = {'input-build', 'hardening-policy', 'production-signing', 'device-acceptance', 'risk-exception', 'production-release', 'incident-response'}
missing = sorted(required - seen)
if missing:
raise SystemExit('missing critical activities: ' + ','.join(missing))
if accountable['production-signing'] == accountable['production-release'] and not data.get('approved_exception'):
raise SystemExit('signing and release share one accountable role without exception')
print(json.dumps({'activities': len(activities), 'critical_complete': True, 'status': 'pass'}, ensure_ascii=False))事故响应在项目开始时就要分工
加固候选上线后若出现大面积崩溃、签名错误、商店拒绝、保护误报或疑似供应链事件,需要立即知道谁冻结候选、谁保全日志与符号、谁联系供应商、谁判断密钥风险、谁决定回滚以及谁向业务与用户沟通。事故发生后再建立群聊不等于责任体系。上线前应演练一次通讯、候选冻结、回滚批准和证据交接,记录替补角色能否在主责缺席时完成相同步骤。
供应商负责解释工具行为、提供映射材料和修复候选;研发负责业务与代码定位;安全负责事件分类、证据和密钥影响;测试负责复现与验证;发布团队负责停止灰度和回滚;业务负责人批准用户影响决策。每个动作保留时间、候选摘要和批准记录。
准备项目分工评估时,应提交活动级 RACI、候选与证明链、签名和发布职责、测试接受、风险例外、事故通讯录和替补角色。申请入口由御盾中央平台统一承接。没有真实执行回执时,矩阵通过只能说明职责设计完整,不能声称项目已交付、兼容通过或风险已经关闭。
事实依据与适用边界
以下内容区分官方事实、本文工程判断和不能外推的范围,避免把设计建议写成未经验证的产品结论。
| 本文判断 | 事实或工程依据 | 适用限制 |
|---|---|---|
| 安全发布需要保留来源、构建、验证与变更证据。 | NIST SP 800-218 SSDF 将安全开发和供应链风险纳入组织实践。 | 组织级框架不定义某个加固产品的功能或项目人员安排。 |
| 构建证明应绑定产物主体、构建者、构建类型、参数和材料。 | SLSA Provenance v1.1 定义构建 provenance 的字段与语义。 | provenance 不单独证明运行安全、兼容或具体人员履责。 |
| 供应链声明应把产物摘要与有类型的负载绑定。 | in-toto Attestation Statement v1 定义 subject、predicateType 和 predicate 结构。 | 格式正确不保证内容真实,仍需信任策略、签名和门禁核验。 |
| Android 发布要区分应用签名密钥、上传密钥、证书和 Play App Signing 责任。 | Sign your Android app 说明 Android 应用签名与密钥职责。 | 文档不能证明实际候选使用正确证书,也不授权供应商持有客户私钥。 |
| Apple 平台通过代码签名、证书和运行验证建立应用身份。 | Apple app code signing process 说明 Apple 应用签名流程。 | Apple 签名链不能与 Android APK 签名方案合并为同一证据。 |
| 发布前需要准备 release 变体、签名产物、测试和依赖服务。 | Android publish your app 说明发布准备与上传流程。 | 通用发布指南不证明具体候选可上架,也不替代商店政策审核。 |
| 每个关键活动应有唯一批准人和至少一个执行人。 | 工程判断:多个或缺失 Accountable 会使批准边界和事故责任无法落地。 | RACI 结构完整不证明人员已经执行或产物已经通过门禁。 |
| 供应商不应默认批准客户风险例外或控制最终生产发布。 | 工程判断:执行方不能替代客户承担业务风险、密钥和商店账号责任。 | 特殊委托需要明确授权、审计、职责分离与到期复核,不能口头默许。 |
工程常见问题
供应商负责加固,能否同时批准保护策略?
不宜默认这样安排。供应商可以执行和建议,客户安全负责人应批准策略,研发确认业务边界,例外由有权承担风险的客户角色批准。
生产签名密钥应该交给加固供应商吗?
原则上由客户受控密钥和发布体系管理。特殊委托必须有明确授权、最小访问、双人审批、审计、撤销和到期安排。
供应商测试通过后,客户是否还要验收?
需要。供应商覆盖工具和通用路径,客户掌握真实业务、账号、数据和设备;最终兼容接受应由客户测试负责人批准。
同一个人能否负责签名并批准发布?
小团队可能兼任,但这是高影响闭环,应显式记录例外、复核人和到期时间,避免无审计的单人发布。
RACI 表通过校验是否代表项目已经交付?
不代表。它只说明职责结构完整;还需要每个角色完成工件、证据、测试、签名和发布门禁,并绑定同一候选。
申请加固项目责任矩阵评估需要准备什么?
准备活动级 RACI、候选证明链、签名与发布职责、测试接受、风险例外、事故响应和替补角色,再通过御盾中央平台提交。