如何在Ubuntu16.04上使用HashiCorpVault安全地管理机密

来自菜鸟教程
跳转至:导航、​搜索

介绍

Vault 是一个开源工具,它提供了一种安全、可靠的方式来存储和分发 API 密钥、访问令牌和密码等秘密。 在部署需要使用机密或敏感数据的应用程序时,Vault 等软件可能至关重要。

在本教程中,您将:

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

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

与管理敏感信息的任何服务一样,您应该考虑阅读有关 Vault 部署最佳实践的其他文档,然后再将其用于类似生产的环境中。 例如,Vault 的生产强化指南 涵盖了策略、根令牌和审计等主题。

先决条件

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

  • 按照 Ubuntu 16.04 的初始设置指南设置一台 Ubuntu 16.04 服务器,包括 sudo 非 root 用户和防火墙。
  • SSL 证书,我们将使用它来保护 Vault 的 HTTP API。 您可以按照这个Certbot独立模式教程免费获得一个。

第 1 步 — 安装 Vault

HashiCorp 将 Vault 作为单个二进制文件提供,因此我们将手动下载并安装 Vault 的可执行文件。

首先,下载适用于 64 位 Linux 的压缩 Vault zip 存档。 您可以在 Vault 的下载页面 上找到最新版本(撰写本文时为 0.9.5)的链接。

wget https://releases.hashicorp.com/vault/0.9.5/vault_0.9.5_linux_amd64.zip

然后下载此文件的校验和,以便验证下载。

wget https://releases.hashicorp.com/vault/0.9.5/vault_0.9.5_SHA256SUMS

接下来,验证 zip 存档的完整性。 这是为了确认 zip 存档的内容与 Hashicorp 在 Vault 0.9.5 版本中发布的内容相匹配。

grep linux_amd64 vault_*_SHA256SUMS | sha256sum -c -

SHA256SUMS 文件中的每一行都有一个校验和和一个文件名,对应于 HashiCorp 提供的每个 zip 存档。 上述命令的 grep 部分打印带有 64 位 Linux 二进制文件的校验和和文件名的行,然后将该行通过管道 (|) 传递到下一个命令。 SHA-256 命令检查 -c,该行中文件名的文件是否与该行中的校验和相匹配。

运行该命令应指示存档为 OK。 如果没有,请尝试重新下载文件。

Outputvault_0.9.5_linux_amd64.zip: OK

校验和验证完成后,安装 unzip 命令,以便您可以解压缩存档。 首先确保您的软件包存储库是最新的。

sudo apt-get update
sudo apt-get install unzip

然后将 Vault 二进制文件解压缩到工作目录中。

unzip vault_*.zip
OutputArchive:  vault_0.9.5_linux_amd64.zip
  inflating: vault 

将 Vault 可执行文件移动到系统的 PATH 中的目录中,以使其可以从您的 shell 访问。

sudo cp vault /usr/local/bin/

最后,在二进制文件上设置一个 Linux 功能标志。 这通过让二进制文件执行内存锁定而不不必要地提升其权限来增加额外的安全性。

sudo setcap cap_ipc_lock=+ep /usr/local/bin/vault

您现在可以使用 vault 命令。 尝试检查 Vault 的版本以确保其正常工作。

vault --version
OutputVault v0.7.2 ('d28dd5a018294562dbc9a18c95554d52b5d12390')

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

第 2 步 - 创建 Vault 单元文件

Systemd 是 Ubuntu 的初始化系统,除其他外,它管理系统的服务。 为了将 Vault 设置为系统服务,我们需要设置以下内容:

  • Vault 守护程序运行的系统用户
  • 用于存储 Vault 信息的数据目录
  • 保险柜的配置文件
  • systemd 单元文件 本身。

注意:在本教程中,我们使用 文件系统后端 将加密的机密存储在 /var/lib/vault 的本地文件系统上。 这适用于不需要复制的本地或单服务器部署。 其他 Vault 后端,例如 Consul 后端,将在分布式密钥/值存储中存储静态的加密秘密。


首先,创建一个vault系统用户。

sudo useradd -r -d /var/lib/vault -s /bin/nologin vault

在这里,我们使用 /var/lib/vault 作为用户的主目录。 这将用作 Vault 数据目录。 我们还将 shell 设置为 /bin/nologin 以将用户限制为非交互式系统帐户。

/var/lib/vault 的所有权设置为 vault 用户和 vault 组独占。

sudo install -o vault -g vault -m 750 -d /var/lib/vault

现在让我们设置 Vault 的配置文件,/etc/vault.hcl。 您将使用它来控制 Vault 中的各种选项,例如存储加密机密的位置。

使用 nano 或您喜欢的文本编辑器创建 vault.hcl

sudo nano /etc/vault.hcl

将以下内容粘贴到文件中,并确保替换为您自己的域名:

/etc/vault.hcl

backend "file" {
        path = "/var/lib/vault"
}

listener "tcp" {
        tls_disable = 0
        tls_cert_file = "/etc/letsencrypt/live/example.com/fullchain.pem"
        tls_key_file = "/etc/letsencrypt/live/example.com/privkey.pem"

}

此配置文件指示 Vault 将加密的机密存储在磁盘上的 /var/lib/vault 中,并指示 Vault 应使用 Let's Encrypt 教程生成的证书通过 HTTPS 侦听连接。

保存并关闭文件,然后通过仅允许 vault 用户读取它来保护 Vault 配置文件的权限。

sudo chown vault:vault /etc/vault.hcl 
sudo chmod 640 /etc/vault.hcl 

接下来,要让 Systemd 管理持久性 Vault 守护程序,请在 /etc/systemd/system/vault.service 处创建一个 单元文件

sudo nano /etc/systemd/system/vault.service

将以下内容复制并粘贴到文件中。 这允许 Vault 作为持久系统服务守护程序在后台运行。

/etc/systemd/system/vault.service

[Unit]
Description=a tool for managing secrets
Documentation=https://vaultproject.io/docs/
After=network.target
ConditionFileNotEmpty=/etc/vault.hcl

[Service]
User=vault
Group=vault
ExecStart=/usr/local/bin/vault server -config=/etc/vault.hcl
ExecReload=/usr/local/bin/kill --signal HUP $MAINPID
CapabilityBoundingSet=CAP_SYSLOG CAP_IPC_LOCK
Capabilities=CAP_IPC_LOCK+ep
SecureBits=keep-caps
NoNewPrivileges=yes
KillSignal=SIGINT

[Install]
WantedBy=multi-user.target

服务单元选项的完整列表很广泛,但在上述定义中需要注意的最重要的配置选项包括:

  • ConditionFileNotEmpty 确保 /etc/vault.hcl 配置文件存在。
  • UserGroup,它们控制 Vault 守护程序运行时使用的用户权限。
  • ExecStart,它指向我们之前安装的可执行文件,并定义了开始运行服务的内容。
  • ExecReload,在 Vault 重新加载其配置文件时调用,例如,在运行 systemctl reload vault 时。
  • [Install],它让我们在启动时持续运行这个服务,所以我们不需要在重启后手动启动它。

最后,Vault 需要读取您使用 Certbot 创建的证书的权限。 默认情况下,这些证书和私钥只能由 root 访问。 为了使这些文件安全可用,我们将创建一个名为 pki 的特殊组来访问这些文件。 我们将创建组,然后将 vault 用户添加到其中。

保存并关闭文件,然后创建 pki 组。

sudo groupadd pki

更新/etc/letsencrypt目录下两个目录的权限,允许pki组读取内容。

sudo chgrp pki /etc/letsencrypt/{archive,live}
sudo chmod g+rx /etc/letsencrypt/{archive,live}

然后将 vault 用户添加到 pki 组。 这将授予 Vault 对证书的访问权限,以便它可以通过 HTTPS 安全地处理请求。

sudo gpasswd -a vault pki

为方便起见,最后一步是在 /etc/hosts 中添加一条规则,将对 Vault 的请求定向到 localhost

默认情况下,Vault 将仅侦听来自环回接口(lo 或地址 127.0.0.1)的请求。 这是为了确保服务在得到适当保护之前不会暴露在公共互联网上。 您可以稍后更新,但目前,此配置更改将让我们使用 vault 命令并正确解析 HTTPS 安全域名。

将以下命令中的 example.com 替换为您获得 Let's Encrypt 证书的域:

echo 127.0.0.1 example.com | sudo tee -a /etc/hosts

这会将行 127.0.0.1 example.com 附加到 /etc/hosts 以便对 example.com 的任何 HTTP 请求都路由到 localhost

设置 Vault 可执行文件、写入服务文件和完成 Vault 配置文件后,我们现在可以启动 Vault 并初始化机密存储。

第 3 步 — 初始化 Vault

当您第一次启动 Vault 时,它将未初始化,这意味着它还没有准备好获取和存储数据。

第一次启动 Vault 时,实际存储加密机密的后端也未初始化。 启动 Vault 系统服务以初始化后端并开始运行 Vault 本身。

sudo systemctl start vault

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

sudo systemctl status vault

该命令的输出应包括有关正在运行的服务的几条信息,例如其进程 ID 和资源使用情况。 确保输出中包含以下行,这表明服务正在正确运行。

Output. . .
Active: active (running)
. . .

如果该服务未处于活动状态,请查看命令输出末尾的随附日志行以查看 Vault 的输出,这有助于查明任何问题。

接下来,我们将设置一个环境变量来告诉 vault 命令如何连接到 Vault 服务器。 此处,Vault 已配置为仅侦听本地环回接口,因此将 VAULT_ADDR 环境变量设置为本地 HTTPS 端点。

export VAULT_ADDR=https://example.com:8200

vault 命令现在可以与守护进程通信。 请注意,定义实际主机名而不是简单地 localhost127.0.0.1 是正确验证 HTTPS 证书所必需的。

通过检查其状态来确认保管库处于未初始化状态。

vault status

服务器应返回 400 错误,表示服务器尚未初始化。

OutputError checking seal status: Error making API request.

URL: GET https://example.com:8200/v1/sys/seal-status
Code: 400. Errors:

* server is not yet initialized

Vault 将在初始化时公开两条信息,这些信息将 not 在任何其他时间点可用:

  • 初始根令牌。 这相当于您的 Vault 部署的 root 权限,它允许管理所有 Vault 策略、装载等。
  • 开封键。 这些用于在守护程序启动时解封 Vault,这允许 Vault 守护程序解密后端秘密存储。

更具体地说,Vault 的解封过程使用由密钥共享形成的密钥对后端进行解密。 也就是说,在初始化 Vault 时,您可以选择创建多少个解封密钥,以及在解封时需要多少个才能成功解封 Vault。

解封参数的一个典型的简单值是创建三个密钥,并且在解封时至少需要其中两个密钥。 这允许将重要的密钥共享分开并存储在不同的位置,以确保妥协的一个不足以解封 Vault。

换句话说,每当启动 Vault 时,将需要 至少两个 解封密钥,以使服务变得可用并准备好使用。 在密封时,存储实际秘密值的文件将保持加密且不可访问。

使用上述参数初始化 Vault:

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

以安全的方式保存每个开封令牌和初始根令牌。 例如,一种选择是将一个解封密钥存储在密码管理器中,另一个存储在 USB 驱动器上,另一个存储在 GPG 加密文件中。

您现在可以使用新创建的解封令牌解封 Vault。 首先使用一把钥匙开封。

vault operator unseal

该命令将要求一个开封令牌:

OutputKey (will be hidden):

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

OutputSealed: true
Key Shares: 3
Key Threshold: 2
Unseal Progress: 1
Unseal Nonce: 3bdc838e-1b74-bc13-1d6f-c772f1694d83

再次运行 unseal 命令。

vault operator unseal

并输入与您已经使用的不同的令牌:

OutputKey (will be hidden):

该命令的输出表明解封过程并成功完成。

OutputSeal Type       shamir
Sealed          false
Total Shares    3
Threshold       2
Version         0.9.5
Cluster Name    vault-cluster-5511b3ff
Cluster ID      53522534-8ee1-8aec-86db-e13e4a499dd0
HA Enabled      false

Vault 现在已启封并可以使用。 每当 Vault 启动或重新启动时,这些解封步骤都是必需的。

但是,解封是与 Vault 的正常交互(例如读取和写入值)不同的过程,后者由 tokens 进行身份验证。 在最后一步中,我们将创建必要的访问令牌和策略来存储秘密值并读取/写入 Vault 中的特定路径。

第 4 步——阅读和写作秘籍

在 Vault 文档 中列举了几个 秘密后端,但对于本示例,我们将使用 通用秘密后端 。 此后端在 Vault 中存储简单的键/值对。

首先,将之前生成的根令牌保存到 shell 变量中以方便使用。

root_token=your_root_token_here

首先,将值写入 Vault 中的路径。

VAULT_TOKEN=$root_token vault write secret/message value=mypassword

在此命令中,secret/ 前缀表示我们正在写入安装在 secret 路径的 generic 后端,我们将密钥 value 存储在路径 message 的值为 mypassword。 我们使用具有超级用户权限的根令牌来编写通用密钥。

在实际场景中,您可以存储外部工具可以使用的 API 密钥或密码等值。 尽管您可以使用根令牌再次读取密钥值,但生成一个对我们的单个密钥具有只读权限的特权较低的令牌是说明性的。

创建一个名为 policy.hcl 的文件。

nano policy.hcl

使用以下 Vault 策略填充文件,该策略定义了对工作目录中秘密路径的只读访问权限:

政策.hcl

path "secret/message" {
     capabilities = ["read"]
}

保存并关闭文件,然后将此策略写入 Vault。 以下命令将创建一个名为 message-readonly 的策略,该策略具有该策略的权限。

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

您现在可以使用策略中指定的权限创建令牌。

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]

token 值保存到名为 app_token 的变量中。

app_token=your_token_value

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

VAULT_TOKEN=$app_token vault read secret/message
OutputKey                     Value
---                     -----
refresh_interval        768h0m0s
value                   mypassword

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

VAULT_TOKEN=$app_token vault list secret/
OutputError reading secret/: Error making API request.

URL: GET https://example.com:8200/v1/secret?list=true
Code: 403. Errors:

* permission denied

这验证了权限较低的应用程序令牌不能执行任何破坏性操作或访问除了其 Vault 策略中明确规定的那些秘密值之外的其他秘密值。

结论

在本文中,您在 Ubuntu 16.04 上安装、配置和部署了 Vault。 尽管本教程仅演示了非特权令牌的使用,但 Vault 文档提供了有关 存储和访问机密的其他方法 以及 替代身份验证方法 的更多信息。

这些说明以相当基本的方式概述了如何部署和使用 Vault,因此请务必阅读 Vault 文档 并根据您的需要进行适当的配置更改。 一些可用于生产的更改包括:

  • 为日常使用生成特权较低的令牌。 这些令牌应使用的特定策略取决于特定用例,但前面的 app_token 说明了如何创建受限权限令牌和策略。
  • 如果 Vault 被部署为团队服务的一部分,则使用每个团队成员的解封密钥初始化 Vault 可以确保仅当多个团队成员参与该过程时才解密 Vault 的存储。