使用版本控制系统安全管理机密的介绍
介绍
版本控制软件 (VCS) 是大多数现代软件开发实践的重要组成部分。 除了其他好处之外,Git、Mercurial、Bazaar、Perforce、CVS 和 Subversion 等软件允许开发人员保存项目历史的快照,以实现更好的协作、恢复到以前的状态并从意外的代码更改中恢复,并管理相同的多个版本代码库。 这些工具允许多个开发人员安全地处理同一个项目并提供显着的好处,即使您不打算与他人共享您的工作。
尽管将 代码 保存在源代码管理中很重要,但将某些项目资产保留在存储库的 out 中同样重要。 出于性能和可用性原因,最好将二进制 blob 和配置文件等某些数据排除在源代码控制之外。 但更重要的是,出于安全原因,永远不应将密码、机密和私钥等敏感数据检入未受保护的存储库中。
在本指南中,我们将首先讨论如何检查已提交到存储库的敏感数据,并在发现任何材料时介绍一些缓解策略。 之后,我们将介绍一些用于防止向存储库添加机密的工具和技术、在提交之前加密敏感数据的方法以及安全机密存储的替代方案。
检查 Git 存储库中的敏感数据
在设置系统来管理您的敏感数据之前,最好检查您的项目文件中是否已经存在任何秘密材料。
扫描您的项目
如果您知道要搜索的确切字符串,则可以尝试使用 VCS 工具的本机搜索功能来检查提供的值是否存在于任何提交中。 例如,使用 git
,这样的命令可以搜索特定密码:
git grep my_secret $(git rev-list --all)
这将在您的整个项目历史记录中搜索指定的字符串。
许多专用工具可以帮助更广泛地揭示秘密。 gitrob 之类的工具可以扫描 GitHub 组织中的每个存储库,以查找与预定义列表中的文件名匹配的文件名。 git-secrets 项目可以根据文件路径和内容中的模式在本地扫描存储库以查找已定义的秘密。 truffleHog 工具使用不同的方法,通过在存储库中搜索可能代表应用程序使用的生成秘密的高熵字符串。 为了将其中一些功能组合到一个工具中,git-all-secrets 将上述工具粘合在一起或在统一界面中重新实现上述工具。
缓解选项
如果您发现不应该提交的文件或数据,请务必做出适当的响应以减轻泄露数据的影响。 正确的行动方案将取决于存储库的共享范围、暴露材料的性质,以及您是否希望删除所有提及的泄露内容或只是使其无效。
如果凭据已提交到您的项目存储库,您的第一步应该是立即更改密码或密码以使先前的值无效。 由于某些原因,无论存储库是否共享或共享范围如何,都应该完成此步骤。 协作要求可能会在项目的整个生命周期中发生变化,从而导致比以前预期的更大的曝光率。 即使您知道您永远不会故意共享您的项目,安全事件也可能将数据泄露给意外方,因此最好主动更改当前值。
虽然您应该在所有情况下轮换被泄露的凭据,但您可能希望从您的 VCS 历史记录中完全删除泄露的凭据或文件。 这对于无法更改的敏感数据尤其重要,例如任何无意提交的用户数据。 从存储库中删除数据涉及重写 VCS 历史记录以从以前的提交中删除文件。 这可以使用本地 git 命令或借助一些专用工具 来完成 。 重要的是要注意,即使您删除了存储库中的所有数据记录,之前复制代码库的任何人仍然可以访问敏感材料。 在评估影响程度时请记住这一点。
如果您怀疑机密被泄露,最好查看与这些程序或服务相关的日志数据,以确定是否存在异常访问或行为。 这可能采取异常活动或请求的形式,这些活动或请求通常源自您的内部网络,来自您无法控制的地址。 此调查将帮助您确定适当的后续步骤来保护您的基础架构和数据。
使用 VCS 功能避免提交机密
在查看外部工具之前,最好先熟悉 VCS 工具的一些固有特性和功能,以帮助防止将不需要的数据提交到存储库。
忽略敏感文件
将包含敏感数据的文件保留在存储库之外的最基本方法是从一开始就利用 VCS 的忽略功能。 VCS “忽略”文件(如 .gitignore
)定义应从存储库中排除的模式、目录或文件。 这些是防止意外暴露数据的第一道防线。 此策略很有用,因为它不依赖外部工具,自动为协作者配置排除项目列表,并且易于设置。
虽然 VCS 忽略功能可用作基线,但它依赖于保持忽略定义是最新的。 在更新或实施忽略文件之前,很容易意外提交敏感数据。 忽略模式仅具有文件级别的粒度,因此如果机密与应提交的代码或其他数据混合在一起,您可能必须重构项目的某些部分。
在提交之前使用 VCS 挂钩检查文件
大多数现代 VCS 实现包括一个称为“钩子”的系统,用于在存储库中执行某些操作之前或之后执行脚本。 此功能可用于执行脚本以检查敏感材料的未决更改的内容。 前面提到的 git-secrets 工具能够安装 pre-commit
钩子,实现自动检查它评估的内容类型。 您可以添加自己的 自定义脚本 来检查您想要防范的任何模式。
存储库挂钩提供了一种更加灵活的机制,用于在提交时搜索和防止添加敏感数据。 这种增加的灵活性是以必须为您想要实现的所有行为编写脚本为代价的,这可能是一个困难的过程,具体取决于您要检查的数据类型。 另一个考虑因素是挂钩不像忽略文件那样容易共享,因为它们不是其他开发人员复制的存储库的一部分。 每个贡献者都需要在他们自己的机器上设置挂钩,这使得执行变得更加困难。
将文件显式添加到暂存区
虽然在范围上更加本地化,但一种可以帮助您更加注意提交的简单策略是仅按名称显式地将项目添加到 VCS 暂存区域。 虽然通过通配符或扩展添加文件可以节省一些时间,但有意添加要添加的每个文件可以帮助防止意外添加可能包含在内的内容。 这样做的一个有益的副作用是,它通常允许您创建更有针对性和一致的提交,这有助于协作工作的许多其他方面。
在存储库中存储加密的秘密
虽然在许多情况下建议从代码存储库中完全删除敏感数据,但有时在存储库中包含一些敏感数据以供其他特权用户访问是必要或有用的。 为此,您可以使用各种工具加密存储库中的敏感文件,同时让每个人都可以访问大多数文件。
实现
有许多不同的软件可以简化部分存储库加密。 大多数工作都遵循相同的基本原则,但每个都提供了独特的实现,根据您的项目需求可能会提供一些引人注目的优势。
一个名为 git-secret 的项目(不要与前面提到的 git-secrets
工具混淆)可以使用可信合作者的 GPG 密钥对机密文件的内容进行加密。 通过利用现有的信任网络,git-secret
用户可以通过指定应该能够解密每个项目的用户来管理对文件的访问。 如果用户已将其公钥发布到密钥服务器,您可以让他们访问加密内容,而无需直接询问他们的密钥。
git-crypt 工具的工作方式与 git-secret
类似,它允许您加密和提交存储库的部分内容,并使用其 GPG 密钥管理对其他贡献者的访问。 如果您的团队不使用 GPG 或者该管理模式对于您的用例而言过于复杂,则 git-crypt
项目可以选择使用对称密钥加密。 此外,git-crypt
将在提交时自动加密,并在克隆时使用 git
过滤器和差异属性进行解密,从而简化管理。
BlackBox 项目 是另一种依靠 GPG 协作加密内容的解决方案。 与以前的工具不同,BlackBox 与许多不同的版本控制系统一起工作,因此可以跨不同的项目使用。 最初设计为 Puppet 生态系统的工具,经过重构以支持更开放的基于插件的系统。 BlackBox 可以随意对单个文件进行加密和解密,还提供了一种透明调用文本编辑器的机制,该编辑器对文件进行解密,打开编辑器,然后在保存时重新加密。
除了上述通用解决方案之外,还有一些解决方案可用于特定类型的存储库。 例如,从 5.1 版开始,Ruby on Rails 项目可以使用在存储库之外设置主密钥的系统在存储库 中包含 加密的秘密。
好处
加密您的秘密数据并将其提交到您的存储库有助于使您的凭证保持最新并与代码使用它们的方式保持同步。 这可以避免机密数据格式或标签的更改与代码使用或访问它的方式之间的偏差。 可以在不引用外部资源的情况下对代码库进行更改。
此外,用代码保密可以大大简化部署。 与其从多个位置提取信息以获得功能齐全的系统,不如将信息全部打包在一个单元中,其中一些组件需要解密。 如果您没有设置支持外部机密存储的基础架构,或者如果您希望最大限度地减少部署项目所需的协调量,这将非常有用。
使用工具对存储库中的敏感信息进行加密的总体优势在于,无需额外的基础设施或规划即可轻松实施加密。 用户可以在几分钟内从将秘密存储为纯文本数据转换为安全的加密系统。 对于具有单个开发人员或小型静态团队的项目,这些工具可能会满足所有秘密管理要求,而不会增加大量复杂性。
缺点
与任何解决方案一样,这种秘密管理方式需要权衡取舍。
从根本上说,秘密是配置数据,而不是代码。 虽然部署在各种环境中的代码可能相同,但配置可能会有很大差异。 通过对存储库中的代码保密,跨不同环境维护配置变得更加困难,并鼓励以对安全性产生负面影响的方式重用凭证。
同样,在存储库中配置对加密机密的细粒度、多级访问通常很困难。 所需的访问控制级别通常比用于在 VCS 中加密机密的工具轻松建模的级别要复杂得多,尤其是对于大型团队和项目而言。 从项目中引入协作者或删除贡献者涉及重新加密存储库中包含敏感数据的所有文件。 虽然这些实用程序通常可以轻松更改用于保护文件的加密,但在这些情况下,这些文件中的机密应该 也 轮换,这可能是一个困难的手动过程。
一个经常被忽视的重要一点是,用于解密数据的密钥通常与加密内容一起存储。 在开发人员的笔记本电脑上,可以解密敏感数据的 GPG 密钥通常存在并且无需任何进一步输入即可使用。 您可以通过使用 GPG 密码来缓解这种情况,但这对于大型团队来说很难实施。 如果团队成员的笔记本电脑遭到入侵,则可以像访问纯文本一样访问项目中最敏感的数据。
一般来说,长期保护存储库中的机密可能很困难。 诸如回滚代码更改之类的简单操作可能会意外地重新引入以前删除的访问权限。 如果暴露了私钥,则可以从存储库历史中恢复和解密历史值。 尽管 VCS 历史记录提供了加密更改日志,但没有审计秘密访问的方法来帮助确定异常访问。
使用配置管理系统进行秘密管理
许多用户对更集中的秘密管理的第一次体验是使用配置管理工具。 因为这些工具负责从一个集中位置协调许多不同机器的配置,所以需要某种程度的秘密管理来确保节点只能访问它们需要的值。
实现
Chef 加密数据包 和 chef-vault 为 Chef 管理的基础设施提供了一些集成的机密管理功能。 加密数据包用于保护敏感值不出现在修订历史中或使用共享机密出现在其他机器上。 Chef-vault 允许使用目标计算机的公钥对机密进行加密,从而提供进一步的安全性,将解密功能隔离到预期的接收者。
同样,Puppet 的 Hiera 键值存储系统可以与 Hiera eyaml 一起使用,以安全地管理特定基础架构组件的机密。 与其他一些系统不同,Hiera eyaml 了解 YAML 的语法和结构,这是 Hiera 使用的数据序列化格式,允许它只加密敏感值而不是整个文件。 这使得在大多数任务中使用普通工具处理包含加密数据的文件成为可能。 由于后端是可插拔的,团队可以实施 GPG 加密来轻松管理访问。
Saltstack 使用 Pillars 来存储指定给某些机器的数据。 为了保护这些项目,用户可以使用 GPG 加密 YAML 值,然后配置 GPG 渲染器 以允许 Salt 在运行时解密这些值。 与 Hiera eyaml 一样,该系统只加密敏感数据而不是完整文件,从而允许正常的文件编辑和差异工具正确运行。
Ansible 包括 Ansible Vault,这是一个加密系统和命令行工具,用于在 playbook 结构中加密敏感的 YAML 文件。 然后 Ansible 可以在运行时透明地解密秘密文件,以结合执行给定任务所需的秘密和非秘密数据。 Ansible Vault 加密整个文件而不是值,因此编辑需要解密并且差异工具无法显示准确的更改信息。 但是,从 Ansible 2.3 开始, 单个变量可以在变量文件 中加密,让用户可以选择如何加密敏感值。
好处
这些解决方案非常适合在配置管理上下文中管理机密所涉及的一些挑战。 他们能够通过利用现有的基础设施库存系统和定义每台机器所需的访问类型的角色指定来协调对机密的访问。 确保每台机器获得正确配置的相同机制可以确保仅将机密传递给需要它们的主机。
使用现有基础架构管理和部署系统的原生工具可最大限度地降低实施加密的运营成本。 使用环境中的本机工具将机密迁移到加密更容易,并且无需额外步骤即可更简单地合并机密的运行时解密。 如果您已经在使用配置管理系统,那么使用其包含的秘密管理机制可能是保护敏感数据最简单的第一步。
缺点
紧密集成意味着用户可以使用他们现有的系统来管理他们的秘密,但这确实意味着这些解决方案被锁定在他们各自的配置管理工具中。 在其他环境中使用这些策略中的大多数将是困难或不可能的,这意味着您正在添加对配置管理工具本身的依赖。 与单一平台的紧密集成也可能会给需要访问数据的外部系统带来问题。 在某些情况下,如果没有外部 API 或可调用命令,除非通过配置管理系统进行访问,否则机密可能会被有效地“捕获”,这可能会受到限制。
在应用程序存储库中存储加密机密的许多缺点也适用于使用配置管理系统存储机密。 与将带有应用程序存储库的笔记本电脑作为妥协的载体不同,任何带有配置管理存储库的笔记本电脑或计算机同样容易受到攻击。 从根本上说,任何同时具有加密值和解密密钥的系统都容易受到这种类型的攻击。
一个相关的问题是,虽然配置管理系统能够确保只有正确的机器才能访问机密,但定义细粒度的访问控制来限制团队成员通常更加困难。 某些系统只能使用单个密码或密钥进行加密,从而限制了划分团队成员对机密的访问权限的能力。
使用外部秘密管理服务
除了在代码旁边或在配置管理系统中存储加密机密之外,另一种方法是使用专用服务来管理基础设施的敏感数据。 这些服务加密和存储敏感数据,并使用解密的值响应授权请求。 这允许开发人员将他们的敏感材料从他们的存储库中移出,并进入一个旨在为人类用户和应用程序协调加密、授权和身份验证的系统。
实现
HashiCorp 的 Vault 等专用秘密管理服务提供了极大的灵活性和强大的功能,可以在不牺牲可用性的同时保护敏感材料。 Vault 保护静态和传输中的数据,旨在使用各种“后端”来公开不同的功能并管理加密、存储和身份验证的复杂性。 几个关键功能包括配置动态机密的能力(连接服务的短期凭证,即时创建),数据加密作为服务(加密和存储来自外部服务的数据,并在请求时再次提供解密的内容。授权方)和基于租约的秘密管理(在给定的时间内提供访问权限,之后自动撤销访问权限)。 Vault 的可插拔架构意味着存储后端、身份验证机制等。 随着业务需求的变化,它们都可以互换。
Square 的 Keywhiz 秘密管理系统是另一项专用服务,用于为敏感数据提供一般安全性。 与 Vault 一样,Keywhiz 公开了客户端和用户可以用来存储和访问机密的 API。 Keywhiz 提供的一个独特功能是能够使用 FUSE 文件系统公开机密,这是一种虚拟文件系统,客户端可以挂载它以将敏感数据作为伪文件访问。 这种机制允许许多不同类型的程序在没有代理或包装器的帮助下访问它们需要的数据,并且它允许管理员使用普通的 Unix 文件系统权限来锁定访问。
Pinterest 的 Knox 是另一项用于管理机密的服务。 它提供了许多与 Vault 和 Keywhiz 相同的功能。 其他系统中没有的一个功能是通过为密钥版本提供显式状态来随时间轮换密钥的能力。 可以将密钥版本标记为主要版本以指示它是当前的首选密钥,活动以指示它仍然可以使用的版本,或不活动以禁用该版本。 该系统允许管理员在不中断服务的情况下随着时间的推移在一组机器上滚动密钥。
好处
与其他系统相比,专用秘密管理服务具有许多引人注目的优势。 将保护和管理敏感数据的复杂性转移到独立系统上,就无需在应用程序和配置管理存储库中解决这些问题。 这种职责分离通过集中秘密存储和通过严格控制的接口管理访问来简化操作安全模型。 通过提供与系统交互的通用接口,授权用户或客户端可以访问他们的秘密,而不管使用的配置管理系统或 VCS。
从管理的角度来看,秘密管理系统提供了许多其他工具所不具备的独特功能。 加密密钥的轻松轮换以及它们保护的底层机密对于需要协调许多不同敏感值的大型部署和复杂系统非常有用。 无需部署代码或进行任何车队范围内的更改,即可轻松调节和撤销访问权限。 动态机密等功能使机密管理服务器可以访问数据库等外部服务,以按需创建每次使用凭证。 基于短期租约的秘密访问作为一种自动机制来限制或过期访问,而无需明确撤销。
集中式秘密管理提供的最重要的改进之一是可审计性。 上面提到的每个系统都保留了有关何时添加、请求、访问或修改秘密的大量记录。 这有助于发现异常和检测可疑行为,还可以帮助评估任何访问的程度,以防出现泄露。 全面了解组织的敏感数据、设置为控制访问的策略以及有关每次成功和尝试的更改或检索的信息,使团队能够在基础设施安全方面做出明智的决策。
缺点
集中式秘密管理系统的主要缺点是在基础设施和管理方面需要额外的开销。
建立一个集中式系统需要在部署到生产环境之前进行大量的规划、测试和协调。 基础设施启动并运行后,必须更新客户端以查询秘密管理服务器的 API,或者必须配置代理进程以代表需要它的进程获取秘密。 必须建立策略来规定哪些应用程序、基础架构和团队成员应该有权访问每个受保护的值。
由于它保护的数据的价值,秘密管理服务器成为最重要的管理安全环境之一。 虽然集中化最大限度地减少了您需要保护的表面区域,但它使系统本身成为恶意行为者的高价值目标。 虽然许多解决方案包括锁定模式、基于密钥的重新启动和审计日志等功能,但未经授权访问活动的、已解密的秘密存储将需要大量补救措施。
除了配置和安全元素的初始成本之外,通过单一服务提供所有敏感数据会为您的基础架构引入一个额外的关键任务组件。 由于启动新应用程序和日常操作通常需要机密信息,因此机密管理停机时间可能会导致重大中断,在恢复服务之前可能无法解决。 可用性对于负责在这么多不同组件之间进行协调的系统至关重要。
包起来
当您评估在部署期间保护敏感数据和协调必要访问的不同方法时,重要的是要考虑项目的安全性、可用性和需求之间的平衡。 上述解决方案涵盖广泛的用例,并提供不同程度的可扩展性和保护。
您的项目或组织的最佳选择可能取决于您必须保护的敏感数据量、团队规模以及可用于管理不同解决方案的资源。 在大多数情况下,从小处着手并随着情况的变化重新评估您的秘密管理需求是有意义的。 虽然您现在可能只需要保护一些秘密并与一个小团队合作,但未来专用解决方案的权衡可能会变得更加引人注目。