在 GitHub,我们借鉴了自己使用 GitHub 的经验来构建 GitHub。作为一个例子,我们在内部使用了许多 GitHub 的高级安全特性。本文将介绍我们如何在内部推出 Dependabot,以保持 GitHub 的依赖关系最新。我们的产品安全工程团队负责推出的工作,并在整个研发周期中与工程师共同努力,保证他们有信心推出新的特性和新的产品。我们将会提供一些背景,比如 GitHub 的内部安全团队如何看待安全工具,我们如何对待 Dependabot 的推出以及如何将 Dependabot 整合到现有的工程和安全流中。
保持依赖关系最新是维护 GitHub 系统安全的最简单方法之一。近年来,从恶意的 flatmap-stream
包,到最近的 log4shell
漏洞,供应链安全问题日益突出。当软件库中使用已知漏洞的软件依赖时,Dependabot 就会对开发者发出警告。通过将 Dependabot 从内部推广到所有软件,能够测量并大幅降低我们对于已知漏洞的软件依赖的使用。
在产品安全工程方面,我们花费了大量的时间来考虑新的安全工具和流程将会给工程师的日常工作带来怎样的影响。在评估工具和设计推出计划时,我们采用了几个指导原则。比如说,这种新流程的安全性会不会超过了对工程团队的影响?怎样循序渐进地推出并收集反馈?我们对工程师有什么样的期待,怎样才能把这些期望清晰地表达出来呢?
尤其是 Dependabot,这些问题中的某些问题都很好回答。Dependabot 是 GitHub 的原生特性,也就是说,它可以与工程师在 GitHub.com 上的现有工作流进行集成。通过更好地跟踪软件供应链的安全,我们将保证 GitHub 和用户的安全,这超过了对工程团队的任何潜在影响。
我们采用了一个三阶段的过程,在 GitHub 推出 Dependabot:测量 Dependabot 警报的现状,分阶段推出,在组织内逐步启用 Dependabot,最后,专注于补救带有开放式 Dependabot 警报的仓库。
我们的第一个目标是准确测量内部的依赖性现状。我们还不关心任何特定存储库的状态,但希望了解整个公司的总体风险。我们通过建立内部工具,通过公共 GraphQL API 收集整个组织的 Dependabot 警报的统计数据来实现这一目标。尽早建立这种工具,使我们能够持续地收集指标,了解 GitHub 在推出之前、期间和之后的总体趋势。
我们的第一个目标是准确测量内部的依赖性现状。我们还不关心任何特定仓库的状态,但希望了解公司整体的风险。我们利用公共 GraphQL API,构建了一个内部工具来收集整个组织的 Dependabot 警报的统计数据来实现这一目标。尽早构建这种工具可以让我们能够不断收集指标,了解 GitHub 在推出之前、期间和之后的总体趋势。
与其他 GitHub 的高级安全特性类似,Dependabot 可以在组织的管理页面为组织内的所有仓库启用。但是,GitHub 内部拥有数千个仓库,我们意识到如果将 Dependabot 应用于整个组织,将会给团队带来巨大的影响。我们通过两种方法来减轻这种影响:分阶段推出和在全公司范围内频繁沟通。
阶段性的推广使我们能够在进行全公司范围内的推广之前,从初始的仓库拥有者那里获得反馈。我们在内部对 GitHub 的安全工具采用了这种方法,因为我们认为取消发布一个新的工具或者流程将会在公司引起更大的混乱。至于 Dependabot,我们决定先在最活跃的仓库中启用这一特性,以保证我们能够收集到有用的反馈。然后我们把它扩大到更大的子集,并最终在整个组织内启用该特性。
作为一个在多个时区异步工作的高度分散的公司,我们混合使用 GitHub 问题和 GitHub 讨论来与工程师分享新工具和流程。我们的目标是在沟通中,清楚而简明地回答最关键的问题。我们正在做什么?我们为什么要这样做?我们什么时候做这个?最后,我们需要做什么?最后一个问题是关键。我们清楚地表明,我们正在全组织范围内推出 Dependabot,以了解当前风险,尽管我们鼓励版本库所有者升级依赖关系,但是我们并不期待每一个 Dependabot 警报都能立即得到修复。
我们也把这些讨论当作其他相关工作的切入点,例如,我们会鼓励团队在不再使用的情况下将仓库归档。在组织内部,总是会有一些新的工具和特性的早期采用者。尽管我们已经明确地提出了分阶段推出的方案,但是我们同时也鼓励团队立刻使用 Dependabot,因为 Dependabot 对于他们的仓库来说是有用的。
总而言之,我们向 200 个仓库进行了初步推出,在 30 天内又增加了另外 1000 个,并且在首次推出的 45 天后,在整个组织范围内启用。在组织范围内启用后,我们还使用了“自动为新仓库启用”的特性,以确保新仓库在缺省情况下遵循最佳实践。
一旦我们为所有 GitHub 仓库启用了 Dependabot,就可以测量整个公司 Dependabot 警报的总体趋势。通过我们的工具,可以看出,在公司整体上,Dependabot 警报的总体趋势基本不变。我们现在将注意力从测量单个状态转向和仓库拥有者一起来更新我们的依赖关系。
我们通过 GitHub 的内部服务目录工具来管理这个过程。这是在 GitHub 内部运行的服务的单一真相来源,它定义了服务的部署位置、服务的拥有者以及如何联系它们。服务的概念是对仓库的一种抽象。服务目录只跟踪目前在 GitHub 内部部署的仓库,而这只是仓库的一个小子集。通过利用服务目录,我们可以确保将修复工作集中在生产中运行的仓库上,在这些仓库中,存在漏洞的依赖关系会给 GitHub 和我们的用户带来风险。
每个服务都可以有与之相关的特定域的指标,我们已经构建了一种工具,通过 GitHub REST API 不断地拉取 Dependabot 数据,然后将其上传到服务目录:
服务目录允许我们将服务水平目标(service level objective,SLO)分配给各个指标。我们意识到,并非所有的 Dependabot 警报都能立即采取行动。而是,我们为服务拥有者设定了一个现实的宽限期,以便在将一个指标标记为失败之前对 Dependabot 警报进行补救。
在这一点上,服务目录指标显示,大约三分之一的服务有需要补救的 Dependabot 警报。然后,我们需要一个流程,将整个公司的升级依赖关系的工作放在第一位,并对进行管理。我们已经决定将 GitHub 的内部工程基础项目进行集成。这个计划从整个公司的角度审视了服务目录中的各项指标,我们将其视为维护良好、可用和安全的服务的基线。
这项计划涉及优先级:鉴于目前没有达到基线预期的服务,那么服务拥有者现在的优先级是什么?通过将 Dependabot 警报集成到该计划中,它使我们能够清楚地传达依赖性升级与其他基础工作的优先级。这还促进了关于弃用的对话。像所有公司一样,我们的很多内部服务目前或者即将被弃用。通过让这些指标清晰可见,我们可以对那些被弃用的服务维持在生产中的风险进行量化,从而促使服务的拥有者重新确定工作的优先次序,从而彻底地关闭这些服务。
GitHub 的工程基础项目的基石是与工程领导层和服务拥有者进行每月同步的会议。每个月,我们都会为服务拥有者确定在接下来的四个星期内要实现的现实目标,然后根据这些目标审查进展情况。这使得我们可以把一些不确定的任务,即修复所有的开放 Dependabot 警报,分解成一组明确的任务,并在数月之内完成。在将 Dependabot 指标与计划整合后,我们又将其作为工程团队一年中一整个季度的工作重点,这使我们能够在升级服务的依赖性方面形成势头。
我们对 Dependabot 警报的关注是成功的。通过利用工程基础项目,我们将 Dependabot 零警报的服务比例从 68% 提高到 81%。这就意味着在短短三个月内的时间里,就修复了大约 50 个 GitHub 核心服务,其中包括几个进行大规模 Rails 升级的服务,以确保它们使用的是最新版本。由于工程基础项目的持续运行,所以这不是一次性的工作。相反,该计划允许我们随着时间的推移跟踪 Dependabot 的警报指标,如果我们发现它们的趋势不正确时,我们就会进行干预。
在对 Dependabot 进行试验后,我们又将其他 GitHub 高级安全工具和特性,如 CodeQL 纳入我们的工程基础项目。GitHub 将更多的安全警报来源集成到一起,可以更好地理解公司整体的服务状况,从而可以清晰地确定工作的轻重缓急。
作为一个内部安全团队,GitHub 的产品安全工程团队和 GitHub 的企业用户一样都要面对很多挑战。我们利用自身经验来指导 GitHub 特性的设计。我们对组织范围内指标的强调是测量这块工作进展的关键部分。这些反馈信息为设计安全概述特性提供了参考,该特性允许 GitHub 企业用户轻松查看整个组织的 GitHub 高级安全警报的当前状态。
作者介绍:
Phil Turnbull,GitHub 开发者。
原文链接:
https://github.blog/2022-05-25-how-we-use-dependabot-to-secure-github/
领取专属 10元无门槛券
私享最新 技术干货