秘密蔓延:一文了解如何保护您的秘密(下)
导语:您的开发团队多久以明文形式向同事发送 API 密钥或其他敏感数据?虽然这是共享数据最快的方式,但它绝对不是最安全的。
如何使用 Vault 存储和共享机密
添加身份验证方法
我们将使用用户名和密码进行身份验证。默认情况下,它是禁用的,因此我们必须启用它。但在此之前,我们应该使用之前生成的根令牌登录 Vault:
屏幕截图 4. 登录 Vault
现在,我们可以更改身份验证方法和其他受保护的服务器部分。让我们添加身份验证方法:
如果您使用 Web UI 而不是命令行,请按照以下路径启用身份验证方法:访问->身份验证方法->启用新方法->用户名和密码->下一步->启用方法。我们不会在这里更改任何设置,因此您可以保持原样。
屏幕截图 5. 方法验证
现在我们已经设置了用户名和密码身份验证,让我们添加一个秘密引擎。
添加秘密引擎
默认情况下,Vault 仅启用 cubbyhole 作为秘密引擎。至少,它是我们可以用来存储数据的唯一引擎。我们可以通过运行以下命令来检查:
屏幕截图 6. Secrets Engines 选项卡
该引擎允许我们包装和解开我们的秘密以安全地共享它们。包装意味着生成一个具有可配置生存时间 (TTL) 的一次性令牌,该令牌引用了我们的秘密。这个秘密只存在于我们的小房间里,直到令牌被打开或过期。
您可以将 cubbyhole 视为一个键值对,其中一次性令牌是键。它使我们能够安全地共享收件人无法访问的内容,而无需授予他们永久访问权限。这是一种简单、快速且可靠的方式来发送我们不希望以明文形式发送的数据。
然而,Cubbyhole 提供了一种临时且短期的秘密共享方式。这就是我们要添加键值引擎的原因。与 cubbyhole 一样,它遵循键值逻辑,但它允许我们创建、读取、更新和删除键值对。KV 引擎适用于秘密、配置数据或任何其他结构化键值信息的长期存储和管理。
让我们添加一个键值秘密引擎:
按照以下路径启用键值秘密引擎:Secrets -> Enable new engine -> KV。然后,将Path更改为kv-engine并选择Enable Engine。
屏幕截图 7. 启用 KV Secrets 引擎
我们将使用键值引擎的第二个版本。此版本具有一些附加功能,包括秘密的版本控制和恢复已删除的秘密。
现在我们可以添加策略,允许用户使用我们的新秘密引擎存储和读取秘密。
添加策略
我们需要遵循最小特权原则的政策。该原则规定,实体(用户、组等)只能访问完成特定任务所需的资源。
例如,开发人员应该有权访问 API 密钥或开发中所需的其他凭据。另一方面,DevOps 专家需要云托管平台的凭据,但他们不应该能够访问所有其他秘密,因为这会增加秘密泄露的可能性。通过添加特定于应用程序的访问权限,我们可以将访问控制游戏提升到一个新的水平。我们的服务器可能需要数据库凭据,但我们的应用程序不需要。
基本上,策略只是命名为访问控制列表 (ACL)。在此示例中,我们希望用户将机密存储在自己的目录中,任何其他用户都无法访问该目录。
为此,我们将使用 ACL 模板。我们可以在策略中使用双花括号作为模板分隔符。有一些可用的模板参数;您可以在ACL 策略路径模板页面上阅读有关它们的更多信息。
在添加策略之前,让我们找出新身份验证方法的标识符,以便在模板中使用它。
我们可以通过运行以下命令来做到这一点:
您可以在访问器列中看到标识符。通过访问->身份验证方法找到身份验证方法。
屏幕截图 8. 身份验证方法
现在我们可以创建一个策略:
替换< ACCESSOR >为我们在上一步中获得的标识符。
此策略将允许我们的用户在其主目录中创建、读取、删除、列出和更新机密。我们将使用策略路径模板来利用策略规则中的身份参数。这将使我们能够根据身份验证时返回给我们的用户身份属性来微调访问控制。
这些属性可以是任何内容:用户的角色、用户名、电子邮件地址、组成员身份等。根据属性,我们将能够授予不同级别的访问权限,从而遵守最小权限原则。
在此示例中,我们使用用户使用用户名和密码身份验证成功进行身份验证时返回的名称。
注意data 后面的前缀kv-engine。这是第二版的键值存储中实际数据的存储位置。里面还有其他几个路径kv-engine,包括metadata 和delete。您可以在HashiCorp 文档中阅读有关 KV Secrets 引擎的更多信息。
此外,我们还添加了元数据路径的规则。此规则允许我们的用户列出其文件夹内所有存储的密钥。此外,我们还为每个用户添加了列出kv-engine路径内容的权限,以便更轻松地使用 Web UI 进行导航。该规则不允许用户读取kv-engine内文件夹的内容- 只能查看它们。
让我们保存我们的政策:
进入策略->创建 ACL 策略创建 ACL 策略:
屏幕截图 9. 创建 ACL 策略
现在我们拥有一个功能齐全的系统,具有 ACL 策略和身份验证。让我们尝试一下。
使用键值引擎存储和读取机密
现在我们已经添加了身份验证方法,我们可以创建一个新用户。这个过程相当简单:
按照 UI 中的以下路径创建用户: Access -> AuthMethods -> userpass -> Create user。输入用户名和密码,然后添加我们在令牌下拉菜单内的生成令牌的策略部分中创建的策略。
屏幕截图 10. 创建用户
我们创建了一个用户名user和密码1234的用户。我们还将此用户分配给我们创建的策略。
现在我们可以以新用户身份登录:
要在 Web UI 中执行此操作,请使用右上角的下拉菜单从 root 帐户注销,然后选择用户名身份验证方法并输入我们的用户名和密码。
截图11.通过用户名/密码认证方式登录
现在让我们在主目录中添加一些内容:
按照以下路径创建密钥:Secrets -> kv-engine/ -> Create Secret。
屏幕截图 12. 创建秘密
我们可以通过运行以下命令来确认我们的秘密已添加:
要使用 Vault 的 UI 在 KV 引擎中查找您的密钥,请按照以下路径操作:Secrets -> kv-engine/ -> user/。
屏幕截图 13. Secret 添加到 KV 引擎
伟大的!一切正常。让我们尝试阅读我们刚刚添加的秘密:
按照以下路径读取 KV 引擎中的 Secret:Secrets -> kv-engine/ -> user/ -> my-secret。
屏幕截图 14. 读取 KV 引擎中的秘密
让我们通过尝试在用户主目录之外保存新的机密来验证我们的策略是否有效:
按照以下路径尝试创建秘密:Secrets -> kv-engine/ -> Create Secret。
屏幕截图 15. 尝试在用户主目录之外创建机密失败
用户无法在其主目录之外读取或存储机密,就像我们预期的那样。
使用 cubbyhole 引擎实现安全的秘密共享
让我们尝试一下 cubbyhole 秘密引擎。为了共享秘密,我们可以使用 Vault 的 cubbyhole 响应包装。读取秘密时,我们可以添加一个参数,告诉秘密引擎将该秘密包装在一次性令牌中,稍后可以将其解开:
要将您的密钥包装在一次性令牌中,请按照以下路径操作:Secrets -> kv-engine/ -> user/ -> my-secret -> Copy -> Wrap Secret。然后,复制生成的令牌。
屏幕截图 16. 将秘密包装在令牌中
输出包含一个包装令牌,我们稍后可以使用它来解开秘密。指定的参数告诉 cubbyhole 创建的令牌的有效时间(以秒为单位)。在我们的例子中,令牌将在接下来的十分钟内有效。
让我们打开它:
$ vault unwrap $WRAPPING_TOKEN Key Value --- ----- data map[importantValue:secret] metadatamap[created_time:2022-12-29T16:18:45.076362889Z custom_metadata:<nil> deletion_time: destroyed:false version:1]
按照以下路径解包令牌:工具 -> 解包。然后,粘贴 WRAPPING_TOKEN。
屏幕截图 17. 解开令牌
正如你所看到的,我们成功地检索到了秘密。该令牌可以与任何用户共享,使我们能够安全地共享秘密,而无需以明文形式发送它们。
但是,如果我们不想一遍又一遍地复制秘密只是为了与人们分享怎么办?有一个解决方案。
使用策略动态共享秘密
目前,我们只能通过使用 cubbyhole 秘密引擎包装秘密来共享秘密。虽然它肯定比以明文形式发送它们更好,但它仍然需要我们手动包装和发送秘密。如果我们可以共享现有的秘密而不复制它怎么办?
我们之前实施的政策可以帮助我们动态共享。让我们看看如何实现它。
首先,让我们创建另一个我们想要与之分享秘密的用户:
要创建新用户,请遵循以下路径:Access -> AuthMethods -> userpass -> Create user。
屏幕截图 18. 创建新用户帐户
现在,我们希望该用户能够读取kv-engine/data/user/my-secret中的秘密。我们可以添加另一个策略,允许我们的第二个用户读取这个秘密:
我们还可以赋予该用户更改、删除该机密或对其执行任何操作的能力。在某些情况下,您可能也想使用这些访问权限。
现在我们应该保存这个策略,就像我们之前做的那样:
您可以在此处创建另一个策略:策略->创建 ACL 策略。
屏幕截图 19. 创建策略
最后,我们将新策略添加到user2:
您可以在此处编辑您的 user2 :访问->身份验证方法->用户密码-> user2 ->编辑用户。然后,在令牌下拉菜单内的生成令牌的策略部分中添加新策略。
屏幕截图 20. 将策略添加到 user2
向现有用户添加新策略时,添加旧策略也很重要,因为我们会覆盖用户拥有的所有策略。在我们的例子中,我们还应该包括一个模板策略。
让我们以该用户身份登录并检查我们的策略是否有效:
屏幕截图 21. 以 user2 身份登录 Vault
您可以在这里找到秘密:Secrets -> kv-engine/ -> user/ -> my-secret。
屏幕截图 22. 以 user2 身份读取机密
现在 user2 可以读取这个秘密,而无需包装和解开它。此外,如果第一个用户更改密钥,第二个用户将看到最新版本。如果我们知道在某些时候我们可能想要更改秘密,并且有些人应该立即可以访问最新版本,那么这将变得非常方便。
手动创建策略并向用户分配策略很快就会变得乏味,那么我们可以做些什么来让它变得更容易呢?我们能以某种方式自动化它吗?
自动化金库
您可以配置 Hashicorp Vault 以自动加强安全性。我们使用的 Vault 客户端仅向服务器的 API 发送请求。该 API 可用于控制 Vault 的各个方面。因此我们可以使用任何方法发送这些请求。Vault 有许多适用于多种不同编程语言的库,可用于自动化我们手动执行的所有操作:
Go 版Vault SDK
适用于 Python 的hvac(HashiCorp Vault API 客户端)
Ruby 的Ruby Vault
Node.js 的节点库
.NET 的VaultSharp
例如,我们可以根据项目使用的语言,使用这些库之一创建 API 服务器来与 Vault 服务器进行通信。我们的服务器可以暴露更高级别的API,让用户轻松创建账户;存储、读取和共享数据;ETC。
这种自动化可以轻松解决创建和分配策略的繁琐任务。您可以在HashiCorp Vault文档中找到所有与 Vault 的 API 直接通信的库,例如官方的 Go 和 Ruby 库以及很多社区库。您甚至可以使用Vault 的官方 API 文档构建自己的库。
结论
在本文中,我们讨论了秘密蔓延的原因和后果,以及如何使用 HashiCorp Vault 秘密管理工具来防止秘密蔓延。
发表评论