如何在Ubuntu20.04上使用HashiCorpVault安全地管理机密
介绍
Vault 是一个开源工具,它提供了一种安全、可靠的方式来存储和分发 API 密钥、访问令牌和密码等秘密。 在部署需要使用机密或敏感数据的应用程序时,Vault 等软件可能至关重要。
在本教程中,您将:
- 安装 Vault 并将其配置为系统服务
- 初始化加密的磁盘数据存储
- 通过 TLS 安全地存储和检索敏感值
有了一些额外的策略,您将能够使用 Vault 安全地管理各种应用程序和工具的敏感数据。
与管理敏感信息的任何服务一样,您应该考虑阅读有关 Vault 部署最佳实践的其他文档,然后再将其用于类似生产的环境中。 例如,Vault 的生产强化指南 涵盖了策略、根令牌和审计等主题。
先决条件
在开始本指南之前,您需要以下内容:
- 按照 Ubuntu 20.04 的初始设置指南设置一台 Ubuntu 20.04 服务器,包括 sudo 非 root 用户和防火墙。
- TLS 证书,我们将使用它来保护 Vault 的 HTTP API。 您可以按照 this Certbot Standalone mode tutorial for Ubuntu 20.04 免费获得一个。
注意:首次安装包时,Vault 会生成一个自签名的 TLS 证书。 如果您没有与 Vault 一起使用的域名或 TLS 证书,但想按照本教程中的步骤进行操作,您可以通过在本教程中的命令中添加 -tls-skip-verify
标志来跳过 TLS 验证,或者通过定义 VAULT_SKIP_VERIFY
环境变量。
此选项仅适用于试验 Vault,不应在生产环境中使用。
第 1 步 — 安装 Vault
HashiCorp 将 Vault 作为典型的 Debian/Ubuntu 软件包提供,因此我们将通过正常步骤将其软件包存储库添加到我们服务器的软件包源列表中:
首先,将 Hashicorp 的 GPG 密钥 添加到您的包管理器,以便您的系统信任他们的包存储库:
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
然后将存储库本身添加到您的包源列表中,以便定期检查它的更新:
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
然后安装包:
sudo apt install vault
您现在可以使用 vault
命令。 尝试检查 Vault 的版本以确保其正常工作。
vault --version
OutputVault v1.8.5 (647eccfe0bd5817bdd8628f3c3171402dfc8a8fc)
Vault 可执行文件已安装在您的服务器上,因此下一步是将其配置为作为系统服务运行。
第 2 步 — 配置保险库
安装 Vault 包会自动在您的系统上创建一个 vault
vault 用户,并设置一个系统服务以在后台运行 Vault。 为了使用 Let's Encrypt 生成的 HTTPS 证书,我们需要对其默认配置进行一些更改。
注意:在本教程中,默认情况下,Vault 使用 文件系统后端 在本地文件系统 /opt/vault
上存储加密的机密。 这适用于不需要复制的本地或单服务器部署。 其他 Vault 后端,例如 Consul 后端,将在分布式密钥/值存储中存储静态的加密秘密。
Vault 的默认配置存储在 /etc/vault.d/vault.hcl
中。 您将使用此文件来控制 Vault 中的各种选项,例如存储加密机密的位置。
使用 nano
或您喜欢的文本编辑器打开 vault.hcl
。
sudo nano /etc/vault.d/vault.hcl
在包含此块的 #HTTPS listener
下找到文件的 listener "tcp"
部分。 如果你使用的是nano
,你可以按Ctrl+W
然后输入listener “tcp”
直接找到该行:
/etc/vault.hcl
... #HTTPS listener ... listener "tcp" { address = "0.0.0.0:8200" tls_cert_file = "/opt/vault/tls/tls.crt" tls_key_file = "/opt/vault/tls/tls.key" ... }
编辑 tls_cert_file
和 tls_key_file
行以指向您的 Let's Encrypt 证书和密钥文件。 不要忘记用您自己的域名替换每行突出显示的 your_domain
部分。
/etc/vault.hcl
listener "tcp" { ... tls_cert_file = "/etc/letsencrypt/live/your_domain/fullchain.pem" tls_key_file = "/etc/letsencrypt/live/your_domain/privkey.pem" }
注意:您还应该将address = "0.0.0.0:8200"
更改为address = “127.0.0.1:8200”
以阻止外部连接到此服务器。 127.0.0.1
是 localhost 的保留地址。 这是为了确保服务在得到适当保护之前不会暴露在公共互联网上。 您可以稍后更新,但目前,此配置更改将让我们使用 vault
命令并正确解析 HTTPS 安全域名。
保存并关闭文件。 如果您使用的是 nano
,请按 Ctrl+X
,然后在提示保存文件时按 Y
,然后按 Enter
确认。
接下来,vault
系统用户也需要读取这些证书的权限。 默认情况下,这些证书和私钥只能由 root
访问。 为了使这些文件安全可用,我们将创建一个名为 pki
的特殊组来访问这些文件。 我们将创建组,然后将 vault
用户添加到其中。
sudo groupadd pki
更新/etc/letsencrypt
目录下两个目录的权限,允许pki
组的成员读取内容。
sudo chgrp -R pki /etc/letsencrypt/archive sudo chgrp -R pki /etc/letsencrypt/live sudo chmod -R g+rx /etc/letsencrypt/archive sudo chmod -R g+rx /etc/letsencrypt/live
然后将 vault
用户添加到 pki
组。 这将授予 Vault 对证书的访问权限,以便它可以通过 HTTPS 安全地处理请求。
sudo usermod -a -G pki vault
为方便起见,最后一步是在 /etc/hosts
中添加一条规则,将对 Vault 的请求定向到 localhost
。
将以下命令中的 your_domain
替换为您为其获取 Let's Encrypt 证书的域:
echo 127.0.0.1 your_domain.com | sudo tee -a /etc/hosts
此命令将 127.0.0.1 your_domain.com
行附加到 /etc/hosts
以便您在 Vault 服务器上向 your_domain.com
发出的任何 HTTP 请求都会忽略 DNS 并直接发送到 localhost
.
设置 Vault 服务并完成 Vault 配置文件后,我们现在可以启动 Vault 并初始化机密存储。
第 3 步 — 初始化 Vault
当您第一次启动 Vault 时,它将未初始化,这意味着它还没有准备好接收和存储数据。 在本教程的这一部分中,您将启动 Vault 服务器,然后使用一组密钥对其进行初始化,这些密钥将用于解封(打开)Vault 的秘密存储。
第一次启动 Vault 时,实际存储加密机密的后端也未初始化。 启动 Vault 系统服务以初始化后端并开始运行 Vault 本身。
sudo systemctl start vault.service
您可以运行快速检查以确认服务已成功启动。
sudo systemctl status vault.service
您应该会收到类似于以下内容的输出:
Output● vault.service - "HashiCorp Vault - A tool for managing secrets" Loaded: loaded (/lib/systemd/system/vault.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2021-11-16 21:55:13 UTC; 22s ago Docs: https://www.vaultproject.io/docs/ Main PID: 104207 (vault) Tasks: 7 (limit: 1137) Memory: 179.3M CGroup: /system.slice/vault.service └─104207 /usr/bin/vault server -config=/etc/vault.d/vault.hcl
该命令的输出应包括有关正在运行的服务的几条信息,例如其进程 ID 和资源使用情况。 确保输出中包含以下行,这表明服务正在正确运行。
Output. . . Active: active (running) . . .
如果该服务未处于活动状态,请查看命令输出末尾的随附日志行以查看 Vault 的输出,这有助于查明任何问题。
接下来,我们将设置一个环境变量来告诉 vault
命令如何连接到 Vault 服务器。 在 Step 1 中,您将 Vault 配置为仅侦听本地环回接口,因此将 VAULT_ADDR
环境变量设置为本地 HTTPS 端点。
export VAULT_ADDR=https://your_domain:8200
vault
命令现在可以与守护进程通信。 请注意,定义实际主机名而不是简单地 localhost
或 127.0.0.1
是正确验证 HTTPS 证书所必需的。
通过检查其状态来确认 Vault 服务器处于未初始化状态。
vault status
服务器应该返回一些输出,以便您可以知道它正在工作但尚未初始化。
Key Value --- ----- Seal Type shamir Initialized false Sealed true Total Shares 0 Threshold 0 Unseal Progress 0/0 Unseal Nonce n/a Version 1.8.5 Storage Type file HA Enabled false
Vault 将在初始化时公开两条信息,这些信息将 not 在任何其他时间点可用:
- 初始根令牌。 这相当于您的 Vault 部署的 root 权限,它允许管理所有 Vault 策略、装载和机密。
- 开封键。 这些用于在守护程序启动时解封 Vault,这允许 Vault 守护程序解密后端秘密存储。
更具体地说,Vault 的解封过程使用由密钥共享形成的密钥对后端进行解密。 首次初始化 Vault 时,您可以选择创建多少个解封密钥,以及解封时需要多少个才能成功解封 Vault。 详细了解Vault的密封机制,可以参考Vault文档。
解封参数的典型配置是创建三个密钥,并且在解封时至少需要其中两个密钥。 这允许将重要的密钥共享分开并存储在不同的位置,以确保妥协的一个不足以解封 Vault。
换句话说,每当启动 Vault 时,将需要 至少两个 解封密钥,以使服务变得可用并准备好使用。 在密封时,存储实际秘密值的文件将保持加密且不可访问。
使用 -key-shares=3
选项使用三个解封密钥初始化 Vault,并且需要至少两个密钥来使用 -key-threshold=2
标志解封 Vault::
vault operator init -key-shares=3 -key-threshold=2
您将收到如下输出:
OutputUnseal Key 1: eZcJeydRrqeSMZ1zTN+VVll9TFT2KvJy7VlnxUgtvuz5 Unseal Key 2: ntmqCKq8rgNnKT1YSLCjVmCCZBAA3NwUeqxIyRpYD4Wm Unseal Key 3: 3FK1+Hsorh4p8/L9mki3VskaEU2eQhLqGOI/pJkTHMbx Initial Root Token: s.hY0ieybfDqCadz7JpL88uO3x
请务必以安全的方式保存每个解封令牌和初始根令牌。 您将无法再次检索这些密钥和根令牌。 例如,一种选择是将一个解封密钥存储在密码管理器中,另一个存储在 USB 驱动器上,另一个存储在 GPG 加密文件中。
如果再次检查 vault status
,Initialized
状态现在将设置为 true
,Total Shares
和 Threshold
值将反映解封保管库所需的密钥碎片数和最小密钥数。
vault status
Output. . . Initialized true Sealed true Total Shares 3 Threshold 2 Unseal Progress 0/2 . . .
请注意,Unseal Progess
行显示值 0/2
。 使用您新创建的解封令牌开始解封 Vault。 运行 vault operator unseal
命令并在出现提示时输入任何键:
vault operator unseal
该命令将要求一个开封令牌:
OutputKey (will be hidden):
输入后,该命令的输出将指示解封正在进行中,但在 Vault 准备好使用之前仍需要一个解封密钥。
OutputKey Value --- ----- Seal Type shamir Initialized true Sealed true Total Shares 3 Threshold 2 Unseal Progress 1/2 Unseal Nonce 0f3a328b-e0c6-6294-d6a2-56da49271dff Version 1.8.5 Storage Type file HA Enabled false
注意 Unseal Progress 1/2
行在输出中的变化。 再次运行 unseal
命令。
vault operator unseal
并输入与您已使用的密钥不同的密钥:
OutputKey (will be hidden):
该命令的输出表明解封过程已成功完成。
OutputKey Value --- ----- Seal Type shamir Initialized true Sealed false Total Shares 3 Threshold 2 Version 1.8.5 Storage Type file Cluster Name vault-cluster-3042c7bc Cluster ID c3e9d814-cf2a-2901-f0e4-ebc52d29e5cc HA Enabled false
Vault 现在已启封并可以使用。 每当 Vault 启动或重新启动时,这些解封步骤都是必需的。
但是,解封是与 Vault 的正常交互(例如读取和写入值)不同的过程,后者由 tokens 进行身份验证。 在接下来的步骤中,我们将创建必要的访问令牌和策略来存储秘密值并读取/写入 Vault 中的特定路径。
第 4 步——阅读和写作秘籍
有几个 secret backends 可以与 Vault 一起使用,但在本示例中,我们将使用 kv secret backend。 此后端在 Vault 中存储简单的键/值对。 但是,默认情况下不启用它。
在本教程的这一部分,您将启用 kv
秘密后端,然后学习如何读取和写入秘密。
首先,将之前生成的根令牌保存到 shell 变量中以方便使用。
root_token=your_root_token_here
接下来,在使用根令牌进行身份验证时,启用 kv
后端:
VAULT_TOKEN=$root_token vault secrets enable kv
如果命令成功,您将收到如下输出:
OutputSuccess! Enabled the kv secrets engine at: kv/
然后,您可以验证它是否已添加到您的本地可用秘密后端列表中:
VAULT_TOKEN=$root_token vault secrets list
您应该收到如下输出:
OutputPath Type Accessor Description ---- ---- -------- ----------- cubbyhole/ cubbyhole cubbyhole_abc1631b per-token private secret storage identity/ identity identity_631fe262 identity store kv/ kv kv_4d5855c8 n/a sys/ system system_79b13f2f system endpoints used for control, policy and debugging
请注意突出显示的行,表示启用了新的 kv
后端。 现在我们可以用这个后端存储一些数据。
VAULT_TOKEN=$root_token vault write kv/message value=mypassword
在此命令中,突出显示的 kv/
前缀表示我们正在写入安装在 kv
路径的 kv
后端,并且我们正在存储密钥 value
在路径 message
处,值为 mypassword
。 我们使用具有超级用户权限的根令牌来编写通用密钥。
检查您使用 vault read
命令创建的密钥:
VAULT_TOKEN=$root_token vault read kv/message
您应该会收到如下输出,其中包含您创建的密钥的内容:
OutputKey Value --- ----- refresh_interval 768h value mypassword
但是,仅使用根令牌创建、读取和以其他方式与 Vault 交互是不安全的,在团队设置中可扩展,并且不允许对机密进行细粒度的访问控制。 在下一部分中,您将学习如何定义策略和创建额外的访问令牌来限制用户与 Vault 交互的方式。
第 5 步 — 创建授权策略
在实际场景中,您可以存储外部工具可以使用的 API 密钥或密码等值。 尽管您可以使用根令牌再次读取密钥值,但生成一个对我们的单个密钥具有只读权限的特权较低的令牌是说明性的。
在本教程的这一部分中,您将创建一个 Vault 策略,它将强制对机密进行只读访问。 要创建策略,您需要编辑文件,然后使用 vault policy
命令将其加载到 Vault 中。
要开始创建策略,请使用 nano
或您喜欢的编辑器打开一个名为 policy.hcl
的文件:
nano policy.hcl
使用以下 Vault 策略填充文件,该策略定义了对密钥路径的只读访问权限:
政策.hcl
path "kv/message" { capabilities = ["read"] }
保存并关闭文件,然后将此策略写入 Vault。 以下命令会将 policy.hcl
文件加载到 Vault 中并创建一个名为 message-readonly
且具有只读功能的策略
VAULT_TOKEN=$root_token vault policy write message-readonly policy.hcl
接下来,创建一个用于对 Vault 进行只读访问的令牌。 将 -policy=”message-readonly”
标志添加到 vault token create
命令以使用您创建的新策略:
VAULT_TOKEN=$root_token vault token create -policy="message-readonly"
输出将如下所示:
OutputKey Value --- ----- token your_token_value token_accessor your_token_accessor token_duration 768h0m0s token_renewable true token_policies ["default" "message-readonly"] identity_policies [] policies ["default" "message-readonly"]
将突出显示的 your_token_value
值保存到名为 app_token
的环境变量中:
app_token=your_token_value
您可以使用 app_token
的值来访问存储在路径 kv/message
中的数据(Vault 中没有其他值)。
VAULT_TOKEN=$app_token vault read kv/message
OutputKey Value --- ----- refresh_interval 768h0m0s value mypassword
您还可以测试这个非特权令牌不能执行其他操作,例如在 Vault 中列出机密。
VAULT_TOKEN=$app_token vault list kv/
OutputError reading kv/: Error making API request. URL: GET https://your_domain:8200/v1/secret?list=true Code: 403. Errors: * 1 error occurred: * permission denied
这验证了权限较低的应用程序令牌不能执行任何破坏性操作或访问除了其 Vault 策略中明确规定的那些秘密值之外的其他秘密值。 如果您想继续使用只读令牌,请务必将其记录在安全的地方以备将来使用。
结论
在本文中,您在 Ubuntu 20.04 上安装、配置和部署了 Vault。 您还创建了一个分片密钥来解封 Vault,启用 kv
后端机密存储,并定义了一个只读策略来限制用户如何与 Vault 机密进行交互。
尽管本教程仅演示了如何使用非特权令牌,但 Vault 文档有更多示例 存储和访问机密的其他方法 以及 替代身份验证方法 。
这些说明演示了如何部署和使用 Vault 的一些核心功能。 您的需求可能需要其他配置更改和更复杂的策略。 请务必阅读 Vault 文档 并根据您的需要进行适当的配置更改。 一些生产就绪的更改可能包括:
- 为日常使用生成特权较低的令牌。 这些令牌应使用的特定策略取决于您的特定用例,但本教程中的示例
app_token
说明了如何创建受限权限令牌和策略。 - 如果您将 Vault 部署为团队将使用的服务的一部分,请使用每个团队成员的解封密钥初始化 Vault。 这种方法可以确保仅当多个团队成员参与该过程时,Vault 的存储才会被解密。