如何在 Ubuntu 20.04 上使用 HashiCorp Vault 安全地管理机密

介绍

Vault是一个开源工具,提供一个安全,可靠的方式来存储和分发秘密,如API密钥,访问代币和密码。

在本教程中,你将:

  • 安装 Vault 并将其配置为系统服务
  • 启动加密的磁盘数据存储
  • 存储并通过 TLS 安全地检索敏感值

有了一些额外的策略,您将能够使用 Vault 安全地管理各种应用程序和工具的敏感数据。

与管理敏感信息的任何服务一样,您应该考虑阅读有关 Vault 部署最佳实践的其他文档,然后在类似于生产的环境中使用它。

前提条件

在您开始本指南之前,您将需要以下内容:

<$>[注意] 注意: Vault 首次安装包时会生成自签名的 TLS 证书. 如果您没有域名或 TLS 证书可与 Vault 一起使用,但希望遵循本教程中的步骤,您可以通过在本教程中的命令中添加-tls-skip-verify标志或定义VAULT_SKIP_VERIFY环境变量来跳过 TLS 验证。

此选项仅适用于 Vault 实验,不应在生产环境中使用。

步骤 1 - 安装 Vault

HashiCorp 提供 Vault 作为典型的 Debian/Ubuntu 包,所以我们将通过将其包库添加到我们服务器的包源列表的正常步骤:

首先,将 Hashicorp 的 _GPG 键添加到您的包管理器中,以便您的系统信任其包存储库:

1curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -

然后将库本身添加到您的包源列表中,以便检查定期更新:

1sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"

然后安装包:

1sudo apt install vault

您现在可以使用Vault命令. 尝试检查Vault的版本,以确保它工作。

1vault --version
1[secondary_label Output]
2Vault v1.8.5 (647eccfe0bd5817bdd8628f3c3171402dfc8a8fc)

Vault 可执行程序已安装在您的服务器上,因此下一步是将其配置为作为系统服务运行。

步骤 2 – 配置 Vault

安装 Vault 包会自动在您的系统上创建一个 vaultvault 用户,并设置一个系统服务,以便在后台运行 Vault. 我们需要对其默认配置进行一些更改,以便使用 Let's Encrypt 生成的 HTTPS 证书。

美元(注)

** 注意**:在本教程中和默认情况下,Vault 使用 filesystem backend存储在本地文件系统上的加密秘密在 /opt/vault. 这适用于本地或单个服务器的部署,不需要复制。

美元

Vault 的默认配置存储在 `/etc/vault.d/vault.hcl 中,您将使用此文件来控制 Vault 中的各种选项,例如存储加密秘密的地方。

使用nano或您最喜欢的文本编辑器打开vault.hcl

1sudo nano /etc/vault.d/vault.hcl

#HTTPS倾听器下找到文件的倾听器tcp部分,其中包含此块. 如果您正在使用`nano`,您可以按`Ctrl+W`,然后输入`倾听器`tcp,直接找到该行:

 1[label /etc/vault.hcl]
 2...
 3#HTTPS listener
 4...
 5listener "tcp" {
 6  address       = "0.0.0.0:8200"
 7  tls_cert_file = "/opt/vault/tls/tls.crt"
 8  tls_key_file  = "/opt/vault/tls/tls.key"
 9...
10}

编辑 tls_cert_filetls_key_file 行,以指向您的 Let's Encrypt 证书和密钥文件. 不要忘记在每个行中代替自己的域名,而不是突出的 your_domain 部分。

1[label /etc/vault.hcl]
2listener "tcp" {
3...
4  tls_cert_file = "/etc/letsencrypt/live/your_domain/fullchain.pem"
5  tls_key_file = "/etc/letsencrypt/live/your_domain/privkey.pem"
6}

<$>[注] :您还应该将地址 = 0.0.0.0.0:8200更改为`地址 = `127.0.0.1:8200以防止此时此服务器的外部连接。127.0.0.1是仅用于 localhost 的保留地址。这就是为了确保该服务在被正确保护之前不会暴露在公共互联网上。您可以稍后更新此功能,但目前这种配置更改将允许我们使用保管命令并正确解决 HTTPS 保护的域名。

如果您正在使用nano,请按Ctrl+X,然后按Y,当被要求保存文件时,然后按Enter,以确认。

接下来,密钥系统用户还需要允许读取这些证书。默认情况下,这些证书和私钥只能通过访问。为了使这些安全可用,我们将创建一个名为pki的特殊组来访问这些文件。

1sudo groupadd pki

更新/etc/letsencrypt目录中的两个目录的权限,以允许pki组的成员阅读内容。

1sudo chgrp -R pki /etc/letsencrypt/archive
2sudo chgrp -R pki /etc/letsencrypt/live
3sudo chmod -R g+rx /etc/letsencrypt/archive
4sudo chmod -R g+rx /etc/letsencrypt/live

然后将Vault用户添加到pki组,这将允许Vault访问证书,以便它可以通过HTTPS安全地服务请求。

1sudo usermod -a -G pki vault

为了方便,作为最后一步,在/etc/hosts中添加一个规则,将请求直接向 Vault 发送到localhost

在下列命令中,用您获得 Let's Encrypt 证书的域代替 your_domain:

1echo 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 本身。

1sudo systemctl start vault.service

您可以运行快速检查,以确认服务已成功启动。

1sudo systemctl status vault.service

您应该获得类似于以下的输出:

 1[secondary_label Output]
 2 vault.service - "HashiCorp Vault - A tool for managing secrets"
 3     Loaded: loaded (/lib/systemd/system/vault.service; enabled; vendor preset: enabled)
 4     Active: active (running) since Tue 2021-11-16 21:55:13 UTC; 22s ago
 5       Docs: https://www.vaultproject.io/docs/
 6   Main PID: 104207 (vault)
 7      Tasks: 7 (limit: 1137)
 8     Memory: 179.3M
 9     CGroup: /system.slice/vault.service
10             └─104207 /usr/bin/vault server -config=/etc/vault.d/vault.hcl

该命令的输出应包含有关运行服务的若干信息,例如其进程 ID 和资源使用情况。

1[secondary_label Output]
2. . .
3Active: active (running)
4. . .

如果该服务不活跃,请查看命令输出末尾的附加日志行,以查看 Vault 的输出,这可以帮助确定任何问题。

接下来,我们将设置一个环境变量,以告诉‘vault’命令如何连接到 Vault 服务器。在 步骤 1中,您将 Vault 配置为仅在本地 loopback 界面上聆听,因此将‘VAULT_ADDR’环境变量设置为本地 HTTPS 终端点。

1export VAULT_ADDR=https://your_domain:8200

请注意,要正确验证 HTTPS 证书,需要定义实际主机名称而不是简单地定义localhost127.0.0.1

通过检查其状态来确认保险箱服务器处于未初始化状态。

1vault status

服务器应该返回一些输出,以便您可以告诉它正在工作,但尚未初始化。

 1Key Value
 2--- -----
 3Seal Type shamir
 4Initialized false
 5Sealed true
 6Total Shares 0
 7Threshold 0
 8Unseal Progress 0/0
 9Unseal Nonce n/a
10Version 1.8.5
11Storage Type file
12HA Enabled false

Vault 在初始化时会暴露两个信息,而这些信息在其他任何时候都不可用:

  • 初始 root token. 这相当于您的 Vault 部署的 root 权限,这允许管理所有 Vault 策略,安装和秘密。
  • Unseal 密钥. 这些被用来解密 Vault 当 Daemon 启动时,这允许 Vault 主机解密后端秘密仓库。

更具体地说,Vault的解密过程使用由密钥共享组成的密钥来解密后端。当您首次初始化Vault时,您可以选择创建多少解密密钥,以及在解密时需要多少密钥才能成功解密Vault。

解密参数的典型配置是创建三个密钥,并在解密时需要至少两个密钥,这允许重要的密钥部分分开并存储在不同的位置,以确保损害一个不足以解密保险箱。

换句话说,每当 Vault 启动时,至少需要 2 个解密密钥才能使服务可用并准备使用。

使用 -key-shares=3 选项初始化 Vault 用三个解密密钥,并要求至少两个密钥以 -key-threshold=2 旗帜解密 Vault:

1vault operator init -key-shares=3 -key-threshold=2

您将收到如下的输出:

1[secondary_label Output]
2Unseal Key 1: eZcJeydRrqeSMZ1zTN+VVll9TFT2KvJy7VlnxUgtvuz5
3Unseal Key 2: ntmqCKq8rgNnKT1YSLCjVmCCZBAA3NwUeqxIyRpYD4Wm
4Unseal Key 3: 3FK1+Hsorh4p8/L9mki3VskaEU2eQhLqGOI/pJkTHMbx
5
6Initial Root Token: s.hY0ieybfDqCadz7JpL88uO3x

请确保以安全的方式保存每个解密代币和最初的根代币. 您将无法再次检索这些密钥和根代币. 例如,一种选择是将一个解密密钥存储在密码管理器中,另一个存储在USB驱动器上,另一个存储在GPG加密文件中。

如果您再次检查保险箱状态,则初始化状态将设置为真实,总股票门槛值将反映您需要解密保险箱的关键碎片数量和最小钥匙数量。

1vault status
1[secondary_label Output]
2. . .
3Initialized true
4Sealed         	true
5Total Shares   	3
6Threshold      	2
7Unseal Progress	0/2
8. . .

请注意,在Unseal Progess行中显示的值为0/2。 使用您新创建的unseal代币开始解密 Vault。 运行unseal vault operator命令,并在提示时输入您的任何密钥:

1vault operator unseal

命令将要求一个不密封的代码:

1[secondary_label Output]
2Key (will be hidden):

输入后,该命令的输出将表明解密正在进行中,但在 Vault 准备使用之前仍然需要另一个解密密钥。

 1[secondary_label Output]
 2Key Value
 3---                -----
 4Seal Type shamir
 5Initialized true
 6Sealed true
 7Total Shares 3
 8Threshold 2
 9Unseal Progress 1/2
10Unseal Nonce 0f3a328b-e0c6-6294-d6a2-56da49271dff
11Version 1.8.5
12Storage Type file
13HA Enabled false

注意在输出中如何改变Unseal Progress 1/2行,再次运行unseal命令。

1vault operator unseal

然后输入与您已经使用的密钥不同的密钥:

1[secondary_label Output]
2Key (will be hidden):

命令的输出表明,解密过程已经成功完成。

 1[secondary_label Output]
 2Key Value
 3---             -----
 4Seal Type shamir
 5Initialized true
 6Sealed false
 7Total Shares 3
 8Threshold 2
 9Version 1.8.5
10Storage Type file
11Cluster Name vault-cluster-3042c7bc
12Cluster ID c3e9d814-cf2a-2901-f0e4-ebc52d29e5cc
13HA Enabled false

Vault 现在已解密并准备使用,这些解密步骤在启动或重新启动 Vault 时都是必要的。

然而,解密是与 Vault 正常交互(如阅读和写入值)的不同过程,这些值由 tokens 验证。

步骤4:阅读和写作秘密

有几个秘密后端(https://www.vaultproject.io/docs/secrets/index.html),你可以使用与 Vault,但对于这个例子,我们将使用的秘密后端(https://www.vaultproject.io/docs/secrets/kv)。

在本教程的本节中,您将启用kv秘密后端,然后学习如何阅读和写下秘密。

首先,将先前生成的根代币保存到壳变量中,以便于使用。

1root_token=your_root_token_here

接下来,在使用根代码进行身份验证时,启用kv后端:

1VAULT_TOKEN=$root_token vault secrets enable kv

如果命令成功,您将收到如下输出:

1[secondary_label Output]
2Success! Enabled the kv secrets engine at: kv/

然后,您可以验证它已被添加到可用的秘密后端的本地列表中:

1VAULT_TOKEN=$root_token vault secrets list

您应该获得如下类型的输出:

1[secondary_label Output]
2Path Type Accessor Description
3----          ----         --------              -----------
4cubbyhole/    cubbyhole cubbyhole_abc1631b per-token private secret storage
5identity/     identity identity_631fe262 identity store
6kv/           kv kv_4d5855c8 n/a
7sys/          system system_79b13f2f system endpoints used for control, policy and debugging

请注意标注的行表示新的kv后端已启用,现在我们可以与此后端存储一些数据。

1VAULT_TOKEN=$root_token vault write kv/message value=mypassword

在这个命令中,突出的kv/前缀表示我们正在写到位于kv路径上的kv后端,我们正在存储在消息路径上的密钥,其值是mypassword

检查您使用vault read命令创建的秘密:

1VAULT_TOKEN=$root_token vault read kv/message

你应该收到以下的输出,包含你创建的秘密的内容:

1[secondary_label Output]
2Key             	Value
3---             	-----
4refresh_interval	768h
5value           	mypassword

然而,仅使用 Root Token 来创建、阅读和以其他方式与 Vault 进行交互并非安全,在团队设置中无法扩展,并且不允许对秘密进行精细的访问控制。

步骤 5 – 创建授权政策

在现实世界的情况下,您可能会存储外部工具可以消耗的 API 密钥或密码等值. 虽然您可以使用 root token 再次读取秘密值,但创建一个具有仅读权限的更少特权的 token 对于我们的单一秘密是示范的。

在本教程的这个部分中,你将创建一个 Vault 策略,它将强制只读的访问秘密. 为了创建该策略,你需要编辑一个文件,然后使用vault 策略命令将其加载到 Vault。

要开始创建策略,请使用nano或您喜爱的编辑器打开名为policy.hcl的文件:

1nano policy.hcl

使用以下 Vault 策略填充文件,该策略定义了只读的访问到秘密路径:

1[label policy.hcl]
2path "kv/message" {
3     capabilities = ["read"]
4}

保存并关闭文件,然后将此策略写入 Vault. 下面的命令将policy.hcl文件加载到 Vault,并创建一个名为message-readonly的策略,该策略具有只读的功能

1VAULT_TOKEN=$root_token vault policy write message-readonly policy.hcl

接下来,创建一个代币,您将用于只读的 Vault 访问. 将 -policy=message-readonly旗帜添加到vault token create’ 命令中,以使用您创建的新策略:

1VAULT_TOKEN=$root_token vault token create -policy="message-readonly"

结果将是这样的:

 1[secondary_label Output]
 2Key Value
 3---                  -----
 4token your_token_value
 5token_accessor your_token_accessor
 6token_duration 768h0m0s
 7token_renewable true
 8token_policies       ["default" "message-readonly"]
 9identity_policies    []
10policies             ["default" "message-readonly"]

将突出的 your_token_value 值保存到名为 `app_token' 的环境变量中:

1app_token=your_token_value

您可以使用「app_token」的值访问存储在「kv/message」路径中的数据(在 Vault 中没有其他值)。

1VAULT_TOKEN=$app_token vault read kv/message
1[secondary_label Output]
2Key Value
3---                     -----
4refresh_interval 768h0m0s
5value mypassword

您还可以测试这个非特权代币不能执行其他操作,例如在 Vault 中列出秘密。

1VAULT_TOKEN=$app_token vault list kv/
1[secondary_label Output]
2Error reading kv/: Error making API request.
3
4URL: GET https://your_domain:8200/v1/secret?list=true
5Code: 403. Errors:
6
7* 1 error occurred:
8    * permission denied

这验证了较少特权的应用程序代币不能执行任何破坏性操作或访问其他秘密值,除了其 Vault 策略中明确指出的其他值。

结论

在本文中,您安装、配置和部署了Vault在Ubuntu 20.04上,您还创建了一个分割的密钥来解密Vault,启用了kv后端秘密仓库,并定义了一个只读的策略,以限制用户如何与Vault秘密进行交互。

虽然本教程只展示了如何使用非特权代币,但 Vault 文档中还有更多例子: 存储和访问秘密的额外方法以及 替代身份验证方法

这些说明说明了如何部署和使用 Vault 的一些核心功能。您的需求可能需要其他配置更改和更复杂的策略。请确保阅读 Vault 文档并为您的需求做出适当的配置更改。

这些代币应该使用的具体策略取决于您的具体使用情况,但本教程中的例子app_token说明了如何创建有限特权代币和策略。

  • 如果您正在部署 Vault 作为团队使用的服务的一部分,请为每个团队成员启动 Vault 使用解密密钥。
Published At
Categories with 技术
comments powered by Disqus