专业书籍精读 · Accelerate · 第 6 章
Accelerate: The Science of Lean Software and DevOps · Ch 6 · Forsgren, Humble & Kim · 2018
你手机里那些 App,背后都有一群人在赶工做新功能。同时还有另一群人,工作是「别让坏人进来、别让你的身份证号泄出去」。这两群人的关系,在很多公司里长期是敌对的:一边嫌另一边拖进度,一边嫌另一边乱来。第 6 章问的是——这两件事真的只能二选一吗?
按常理,一个团队花在安全上的功夫越多,做新东西的速度就该越慢。可数据查出来是反的:那些交付又快又稳的团队,花在「修安全问题」上的时间,只有落后团队的一半。他们既跑得快,安全上的麻烦还更少。
想象装修房子。设计、砸墙、埋线、刷漆,忙活三个月,全都做完了,最后一天请来一位验收师傅。他一看:墙里该埋的防火材料没埋。
这时候你有两个选择,都很惨:要么砸墙重来,三个月的活白干一大半;要么签个字说「下次注意」,把风险留在墙里。
更要命的是,验收师傅全公司只有一两位,几百个装修队都排队等他。他成了整栋楼的瓶颈。于是大家学会了一件事——绕过他。
这一章的答案不是「多请几个验收师傅」,而是把那道最后的大门,拆成三件平时就做的小事:
一、开工前先请他坐下来聊十分钟。画图纸的时候就问一句「这里会不会出事」,比砸墙便宜一万倍。而且是每个功能都聊,不是攒到最后一次性聊。
二、把检验过的材料直接送到工地。这是最妙的一招:与其派人守在每个工地门口挑毛病,不如把已经合格的水泥、电线、五金件提前备好、随手可取——工人图省事,自然就用了合格的。让做对的事变成最省力的事,比讲一百遍规矩管用。
三、把检查做成流水线上的自动关卡。每次交活儿,机器自动扫一遍:有没有用到已知会漏水的旧管件、有没有把家门钥匙忘在门口。人不用等,几分钟就有回音。
这三件事一起做,那位验收师傅的角色就变了:他不再是站在门口拦人的,而是修路的——他花时间去准备好材料、做好机器,路修好了,几百个装修队自己就能走对。人手不够的问题,就这么绕过去了。
顺带还解决了另一件事:因为问题都是当天发现、当天改,返工量小得多——这就是为什么这些团队反而更快。
安全不是发布前那道门,而是应该拆成零件、平时就做的日常动作;安全团队真正该干的活,是把安全的那条路铺好,让开发走上去比绕开还省事。诚实的代价是——铺路本身是笔前期投入:备好的材料要有人持续更新,机器报错太多、又老报错的地方没错,大家很快就会学会无视它。
想进到具体机制、研究结论、对比表和示意图? → 切到精读版
你以为安全和速度是一个跷跷板——多做安全就慢,跑得快就必然埋雷。这一章用数据把跷跷板拆了:把信息安全(information security,简称 infosec)嵌进日常交付的团队,不但更安全,交付还更快——高效能组花在「修复安全问题」上的时间,比低效能组少约 50%。做法上的转向也很硬:安全团队的产出不再是「评审意见」,而是一条铺好的路——预先批准、开箱即用的库与工具链,加上流水线里自动跑的检查。
CVE-2017-5638)——有编号,工具才能自动比对「你用的版本中不中招」。本章是 Part I「研究发现」的第 6 章,篇幅是全书最短的几章之一,但结论很锋利。上承第 5 章(松耦合架构让团队能独立测、独立发),下启第 7 章(精益管理实践,包括那个著名的结论——外部变更审批委员会并不改善稳定性)。这两章其实是同一个主题的两面:那些以「把关」为名设立的末端关卡,到底在保护你,还是只在制造排队?
对应现实里,本章正是 DevSecOps 这个词的实证底本,也是今天平台工程里「安全铺路(paved road)」、供应链安全(SBOM / SLSA)这些做法的上游。DORA 后来把它固化成一条独立能力条目,从早期的 shifting left on security 演化为今天的 pervasive security(无处不在的安全)。
先把「旧世界的痛」摆成具体场景。一个 40 人的支付团队做了一个季度的新功能,发布前两周安排渗透测试。安全顾问跑了五天,交回 40 条发现,其中 6 条标为「高危、发布前必修」。麻烦在于:有 2 条不是代码 bug,是三个月前定下的设计选择——比如令牌放在哪、有效期多长。改它意味着回到设计、改数据结构、重跑全部测试。
团队只剩两条路:延期(推迟一个月,业务方震怒),或接受风险(签字说下季度再修,然后下季度也不会修)。现实里绝大多数选第二条。这就是末端安全大门最讽刺的地方:它设立的初衷是拦住风险,实际效果却是批量生产「已知且被接受的风险」。
第二重痛是人数的结构性不对称。安全人手相对开发永远是极少数——业界长期流传的经验量级是 开发 : 运维 : 安全 ≈ 100 : 10 : 1(这是 DevOps 社区反复引用的粗略比例,不是本章给出的数据)。在这种比例下,「每个功能都由安全团队人工评审」在算术上就不成立:要么评审变成走过场,要么安全团队变成整条流程上最堵的那一段。
第三重痛是修复成本随时间陡升。同一个问题,白板上改是十分钟讨论,代码评审里改是半小时,上线后再改就要走应急发布、通知下游、可能还有数据回补与对外披露。末端大门恰好把所有发现都堆在了最贵的那一格。
所以本章的问题是:安全能不能不当门,改当路?如果改了,速度会付出代价吗?——第二问的答案,是本章最值钱的那一条。
本章最该被记住的一句是那个统计结果:高效能组花在修复安全问题上的时间,只有低效能组的一半左右。注意这句话的形状——它不是说「高效能组更安全所以慢一点」,也不是说「他们牺牲安全换速度」,而是同一批团队在两个维度上同时更好。
机制不神秘,就是图 1 里那个「返工半径」:安全问题的成本在被发现的那一刻就已由「距离它被引入过了多久」决定。末端大门把所有发现堆在最贵的一格,账单就是三个月的返工;左移把发现摊到沿途,账单就是一次提交的修改。被省下的不是「安全工作」,而是「重做已完成工作」的那部分。
本章由此把安全放进了全书的因果模型:安全左移是一项技术实践,它驱动持续交付能力,持续交付再驱动交付效能与组织绩效。安全不是挂在交付流程旁边的约束,而是交付能力本身的一个组成部分。
第一条实践是:所有重要功能都做安全评审,但评审方式必须不拖慢交付。这后半句是全章最容易被忽略的限定词——它排除了「加一个审批环节」这种解法。
具体形态是两件事。其一,安全人员参与设计阶段:还只有白板和文档时就把威胁建模的三个问题问完——这功能碰什么数据、谁想要它、他从哪进来。这时候改的是设计选择(令牌放哪、默认权限给多大、哪些字段根本不该采集),成本是一次讨论。其二,安全人员参与迭代演示:每个迭代结束的演示邀请安全一起看,用高频小批量的接触,替代低频大批量的一次性评审。
分寸很重要:前移的是「参与」,不是「审批权」。前移之后仍然赋予一票否决 + 排期特权,你得到的只是一道更早的门,前置时间照样被拉长。本章要的是协作者,不是更早的守门人。
第二条实践是本章最有工程含金量的一条:安全团队的产出,应该是让开发者「容易做对」的东西——预先批准、开箱即用的库(library)、包(package)、工具链(toolchain)与流程。
为什么这一条最关键?回到那个 100 : 10 : 1 的人数结构:人工评审的产能随安全团队人数线性增长,而待评审的功能数随开发团队人数增长——一场必输的赛跑。预批准的库不一样,它是「做一次、被用一万次」的资产。安全团队花两周做一个正确的认证库,之后一百个团队每次调用它都不需要安全团队在场。这是把安全从线性产能切到杠杆产能的唯一办法。
业界后来管这套东西叫「铺好的路」(paved road)——平台团队提供一条默认安全的主干道,走它最省事;你也可以下道自己走,但下道就得自己扛评审与举证。关键在于让默认选项是安全的:开发者选组织内部的 HTTP 客户端而不是随手 npm install 一个陌生包,往往不是因为受过安全培训,而是因为前者文档更好、脚手架里本来就有、出问题有人管。
这也解释了为什么「加强安全培训」「发一份安全编码规范」通常收效甚微:它们提高的是「知道该怎么做」,而瓶颈从来是「做对的那条路比做错的更费劲」。
第三条实践是:安全要求与安全测试成为自动化测试套件与部署流水线的一部分,而不是另设一条平行的、由人驱动的流程。
操作上,这意味着安全检查按反馈时延分层放进流水线的不同关卡——和第 4 章的测试金字塔同一个思路:越便宜越确定的放得越靠前,越贵越模糊的放得越靠后。
注意最后一条的转变:渗透测试并没有被废掉,它被移出了关键路径。这是本章「不拖慢交付」那个限定词在流水线上的落地方式——把安全活动分成「必须阻塞的」和「可以异步的」,绝大多数被挪进后者。
落地时真正要做的选择是三个:安全在什么时点介入?哪些检查阻塞发布、哪些不阻塞?安全团队把有限人力投在评审还是铺路?摆成表看:
表 1 · 安全介入时点:同一份工作放在不同位置,成本与效果差一个数量级
| 介入时点 | 能挡住什么 | 反馈时延 | 诚实的代价 | 什么时候该选 |
|---|---|---|---|---|
| 设计期 (威胁建模) | 架构级问题:数据该不该采集、信任边界画在哪、权限模型是否可收敛。后面所有层都补不了这一层 | 一次讨论 | 吃人;需要有经验的安全工程师,无法自动化,也很难对每个小功能都做 | 新系统、碰敏感数据的功能、涉及认证 / 支付 / 权限模型的改动 |
| 编码期 (预批准的库) | 整类实现级漏洞:注入、加密误用、令牌管理错误——靠默认值消除,而不是靠人记得 | 零(开发者根本感觉不到) | 前期投入大;库要有人长期维护、跟版本,弃养的「铺好的路」比没路更危险 | 几乎总该做;组织越大杠杆越高,是安全团队的第一投入方向 |
| 流水线 (自动扫描) | 已知模式:泄露的密钥、带 CVE 的依赖、危险写法、错误的基础设施配置 | 秒到分钟 | 假阳性会腐蚀信任;工具本身要选型、调优、维护,是持续成本不是一次性 | 所有团队的基本盘;从密钥扫描 + 依赖扫描起步收益最快 |
| 预发环境 (DAST) | 运行时与集成态问题:配置错误、认证绕过、暴露的管理端点 | 数十分钟 | 慢、覆盖率取决于爬取质量、需要一个足够像生产的环境 | 对外暴露的 Web / API 服务;内部批处理作业收益有限 |
| 发布前人工大门 (传统渗透测试) | 创造性的攻击链:自动化工具想不到的组合利用 | 数天到数周 | 本章批评的正是把它当门:它把发现堆在最贵的一格,逼团队在「延期」与「接受风险」之间二选一 | 保留它,但移出关键路径:定期做、异步修,用来校准前面几层 |
| 生产运行时 (监控 / 运行时防护) | 前面全漏掉的、以及零日:异常行为、真实攻击流量 | 实时(但已在生产) | 已经在生产了;误伤真实用户的风险,噪声大,需要值班承接 | 高价值、高暴露面的系统;它是兜底,不是前面几层的替代品 |
表 2 · 自动化安全检查的选型:先做哪个、要不要阻断发布
| 检查类型 | 抓什么 | 假阳性 | 建议放置 | 代价 / 坑 |
|---|---|---|---|---|
| 密钥扫描 | 提交里的密码、API 令牌、私钥 | 很低 | 预提交 + CI,硬阻断 | 只拦住新的;历史里已经泄露的必须轮换,删 commit 没用 |
| 依赖扫描 SCA | 用了带已知 CVE 的第三方库版本 | 低(但「可达性」常被高估) | CI 每次构建,按严重级阻断 | 报出的漏洞未必在你的调用路径上;不做可达性分析会淹在待办里 |
| SAST 静态扫描 | 源码里的危险写法(注入、越权、反序列化) | 高,是最大障碍 | 先不阻断,只对本次改动报警;信噪比稳定后再收紧 | 一上来对全量代码开扫会产出几千条历史积压,团队直接放弃 |
| IaC / 配置扫描 | 公开的存储桶、过宽的网络规则、缺失的加密 | 低 | CI,硬阻断 | 规则集要跟着云厂商能力更新;例外要有明确的登记与到期 |
| DAST 动态扫描 | 跑起来才暴露的问题 | 中 | 预发环境定时跑,不阻断 | 慢;覆盖率取决于能不能登录进去爬到深层页面 |
| SBOM 生成 | 不抓漏洞,产出「我由什么构成」的清单 | 不适用 | 构建时产出并归档 | 本身不提供防护;价值在新漏洞爆发时能秒级回答「我中招了吗」 |
如果只能做一件事:先上密钥扫描与依赖扫描。它们规则确定、误报低、覆盖面广,且不需要安全专家在场就能产出结果——正好符合本章「不拖慢交付」的限定。如果能做第二件事:把最常被复制粘贴的那段安全相关代码(认证、加密、输入校验)抽成一个维护良好的库塞进脚手架。这一件事的杠杆通常超过前面所有扫描器加起来。
三条实践今天已是主流工程组织的标准配置,只是名字换了:设计期介入叫威胁建模,预批准的库与工具链叫平台工程 / 铺好的路(paved road),流水线里的自动扫描叫DevSecOps。GitHub 把依赖扫描做成默认开关(Dependabot)、云厂商把 IaC 扫描内置进部署工具,本质都是在替组织完成第二条——让做对的事变成默认选项。
在面试与架构评审里,它给你两个有数据支撑的反问。有人说「要加强安全,所以设一个发布前安全审批」:你怎么保证这道门不变成排队?保证不了的话,它拦住的是风险,还是只是速度?有人说「安全拖慢了我们」:你们的安全工作是在设计期做的,还是在发布前做的?后者的慢是位置造成的,不是安全造成的。
大厂实证
63% 的受访者称已「很大程度」或「完全」落地。更贴合本章的是另一条:报告称高信任、低指责的文化明显更可能采纳这些安全实践,而且「teams who focus on establishing these security practices have reduced developer burnout」(专注建立这些安全实践的团队,开发者倦怠更低)。安全做对了,减轻的是负担,不是增加负担。CVE-2017-5638;上游补丁在 2017 年 3 月就已发布,而入侵发生在同年 5 月之后——中间隔了两个多月,组织内部却没能定位到哪些系统在用这个版本。这正是表 2 里「依赖扫描 + SBOM」那两格要解决的问题:补丁存在从来不是难点,难点是知不知道自己中招。① 核心命题:安全与速度不是跷跷板。把安全嵌进日常交付的团队,两个维度同时更好。
② 最该记住的数字:高效能组花在修复安全问题上的时间,约为低效能组的一半。省下来的不是安全工作,是返工。
③ 机制是「返工半径」:问题的成本由「距离它被引入过了多久」决定。末端大门把所有发现堆在最贵的一格。
④ 末端安全大门最讽刺的效果:它设立的初衷是拦住风险,实际产出却是一批「已知且被接受的风险」——因为发布前两周发现的设计级问题,团队只能在延期与签字之间选。
⑤ 三条实践之一:所有重要功能都做安全评审,但评审方式不得拖慢交付——安全人员进设计阶段与迭代演示,前移的是参与,不是审批权。
⑥ 三条实践之二(杠杆最大):让做对的事最省事——提供预先批准、开箱即用的库、包、工具链与流程。这是把安全团队从线性产能切换到可复用资产的唯一办法,后来被叫作「铺好的路」。
⑦ 三条实践之三:安全测试进部署流水线,按反馈时延分层——秒级密钥扫描硬阻断,分钟级依赖扫描按严重级阻断,SAST 先只报新增改动,DAST 放预发不阻断。
⑧ 渗透测试没被废掉,是被移出关键路径:从「批准这次发布」改为「校准前面几层漏了什么」。
⑨ 落地失败的典型形态:装上扫描器就宣布左移完成,把几千条告警丢给开发——本章说的恰恰相反,安全团队要承担更多工程工作;以及假阳性腐蚀信任后,仪表盘显示「已覆盖」而实际防护为零。
⑩ 读它的分寸:短章、给原则不给手册;自愿问卷 + 推断性分析,因果大概率双向;2018 年成书,之后的供应链攻击与「左移过头」的反弹都是它的必要补丁。