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

介绍

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

在本教程中,你将:

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

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

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

前提条件

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

  • 一个 Ubuntu 16.04 服务器通过以下设置 Ubuntu 16.04 的初始安装指南,包括一个 sudo 非根用户和防火墙。
  • 一个 SSL 证书,我们将使用它来保护 Vault 的 HTTP API。

步骤 1 - 安装 Vault

HashiCorp 提供 Vault 作为单个二进制,所以我们将手动下载和安装 Vault 的可执行。

首先,下载为 64 位 Linux 的压缩 Vault zip 档案. 您可以在 Vault 的下载页面找到最新的版本的链接 (0.9.5 在写作时)。

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

然后下载此文件的支票金额,以便您可以验证下载。

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

接下来,检查 zip 档案的完整性,以确认 zip 档案的内容与 Hashicorp 在 Vault 版本 0.9.5 中发布的内容相匹配。

1grep linux_amd64 vault_*_SHA256SUMS | sha256sum -c -

SHA256SUMS文件中的每个行都有一个检查总和和一个文件名,一个为HashiCorp提供的每个 zip 档案。上面的命令的抓住部分打印了 64 位 Linux 二进制的检查总和和文件名,然后管道(‘ Átha’)将该行带到下一个命令。

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

1[secondary_label Output]
2vault_0.9.5_linux_amd64.zip: OK

完成支票量验证后,安装unzip命令,以便您可以解压缩档案。

1sudo apt-get update
2sudo apt-get install unzip

然后将 Vault 二进制解密到工作目录中。

1unzip vault_*.zip
1[secondary_label Output]
2Archive:  vault_0.9.5_linux_amd64.zip
3  inflating: vault

将 Vault 可执行程序移动到系统的PATH中的目录中,使其从您的壳中可访问。

1sudo cp vault /usr/local/bin/

最后,在二进制上设置一个Linux功能旗帜,这增加了额外的安全性,允许二进制执行内存锁,而不会不必要地提高其特权。

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

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

1vault --version
1[secondary_label Output]
2Vault v0.7.2 ('d28dd5a018294562dbc9a18c95554d52b5d12390')

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

步骤 2:创建 Vault Unit 文件

Systemd 是 Ubuntu 的 init 系统,它管理系统的服务,以便将 Vault 设置为系统服务,我们需要设置以下内容:

  • 一个系统用户为 Vault 演示器运行为
  • 一个数据目录存储 Vault 的信息
  • Vault 配置文件
  • 系统d 单位文件本身。

美元(注)

** 注意**: 在本教程中,我们正在使用 filesystem backend来存储在本地文件系统上的加密秘密在 /var/lib/vault. 这适用于不需要复制的本地或单服务器部署。

美元

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

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

在这里,我们将使用 /var/lib/vault 作为用户的首页目录. 这将被用作 Vault 数据目录. 我们还将壳设置为 /bin/nologin 以限制用户作为非互动系统帐户。

将 `/var/lib/vault’ 的所有权设置为 vault 用户和 vault 组。

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

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

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

1sudo nano /etc/vault.hcl

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

 1[label /etc/vault.hcl]
 2backend "file" {
 3        path = "/var/lib/vault"
 4}
 5
 6listener "tcp" {
 7        tls_disable = 0
 8        tls_cert_file = "/etc/letsencrypt/live/example.com/fullchain.pem"
 9        tls_key_file = "/etc/letsencrypt/live/example.com/privkey.pem"
10
11}

此配置文件指示 Vault 在磁盘上存储加密的秘密 `/var/lib/vault,并表示 Vault 应该使用从 Let's Encrypt 教程生成的证书来收听通过 HTTPS 的连接。

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

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

接下来,要让 Systemd 管理持久的 Vault 对象,请在 /etc/systemd/system/vault.service 创建一个 单元文件

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

将下列内容复制并粘贴到文件中,这样 Vault 就可以在后台运行,作为一个持久的系统服务示威者。

 1[label /etc/systemd/system/vault.service]
 2[Unit]
 3Description=a tool for managing secrets
 4Documentation=https://vaultproject.io/docs/
 5After=network.target
 6ConditionFileNotEmpty=/etc/vault.hcl
 7
 8[Service]
 9User=vault
10Group=vault
11ExecStart=/usr/local/bin/vault server -config=/etc/vault.hcl
12ExecReload=/usr/local/bin/kill --signal HUP $MAINPID
13CapabilityBoundingSet=CAP_SYSLOG CAP_IPC_LOCK
14Capabilities=CAP_IPC_LOCK+ep
15SecureBits=keep-caps
16NoNewPrivileges=yes
17KillSignal=SIGINT
18
19[Install]
20WantedBy=multi-user.target

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

*ConditionFileNotEmpty确保了我们之前安装的ExecStart文件的存在。 *用户控制了Vault daemon将运行的用户权限。 *ExecStart,指向我们之前安装的执行程序,并定义了如何开始运行服务。 *ExecReload,当Vault重新加载其配置文件时,例如,当运行systemctl重新加载柜时。

最后,Vault需要读取您使用Certbot创建的证书的权限。默认情况下,这些证书和私钥只能通过 root访问。

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

1sudo groupadd pki

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

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

然后将 vault 用户添加到 pki 组中,这将允许 Vault 访问证书,以便通过 HTTPS 安全地处理请求。

1sudo gpasswd -a vault pki

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

默认情况下, Vault 只会听取来自 loopback 接口的请求(‘lo’,或地址‘127.0.0.1’)。这就是为了确保服务在被正确保护之前不会暴露在公共互联网上。

在下列命令中,用您已获得 Let’s Encrypt 证书的域代替example.com:

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

这将127.0.0.1 example.com的行添加到/etc/hosts,以便任何HTTP请求到example.com的路由到localhost

随着 Vault 可执行的设置,服务文件被写成,并且 Vault 配置文件完成,我们现在已经准备好启动 Vault 并初始化秘密仓库。

步骤 3 – 初始化 Vault

当您首次启动 Vault 时,它将不初始化,这意味着它尚未准备好获取和存储数据。

第一次启动 Vault 时,实际存储加密秘密的后端也将不初始化,然后启动 Vault 系统服务来初始化后端,然后开始运行 Vault 本身。

1sudo systemctl start vault

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

1sudo systemctl status vault

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

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

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

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

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

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

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

1vault status

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

1[secondary_label Output]
2Error checking seal status: Error making API request.
3
4URL: GET https://example.com:8200/v1/sys/seal-status
5Code: 400. Errors:
6
7* server is not yet initialized

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

  • 初始 root token. 这相当于您的 Vault 部署的 root 权限,这允许管理所有 Vault 策略,安装等。
  • Unseal 密钥. 这些用于在 Daemon 启动时解密 Vault,这允许 Vault 代门解密后端秘密存储。

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

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

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

以上述参数初始化 Vault:

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

例如,一个选项是将一个解密密钥存储在密码管理器中,另一个存储在USB驱动器上,另一个存储在GPG加密文件中。

您现在可以使用新创建的 unseal 代币解密 Vault. 开始使用一个密钥解密。

1vault operator unseal

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

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

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

1[secondary_label Output]
2Sealed: true
3Key Shares: 3
4Key Threshold: 2
5Unseal Progress: 1
6Unseal Nonce: 3bdc838e-1b74-bc13-1d6f-c772f1694d83

再次运行unseal命令。

1vault operator unseal

然后输入一个不同于你已经使用的代码:

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

命令的输出表示解密过程并成功完成。

1[secondary_label Output]
2Seal Type shamir
3Sealed false
4Total Shares 3
5Threshold 2
6Version 0.9.5
7Cluster Name vault-cluster-5511b3ff
8Cluster ID 53522534-8ee1-8aec-86db-e13e4a499dd0
9HA Enabled false

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

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

步骤4:阅读和写作秘密

在 Vault 文档中列出的秘密后端有几种(https://www.vaultproject.io/docs/secrets/index.html),但对于这个例子,我们将使用一般的秘密后端(https://www.vaultproject.io/docs/secrets/generic/index.html)。

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

1root_token=your_root_token_here

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

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

在这个命令中,秘密前缀表示我们正在写到位于秘密路径上的通用后端,我们正在存储在消息路径上的钥匙,值是mypassword

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

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

1nano policy.hcl

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

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

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

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

您现在可以创建一个代币,使用政策中指定的权限。

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]

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

1app_token=your_token_value

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

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

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

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

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

结论

在本文中,您已在Ubuntu 16.04上安装、配置和部署了Vault,虽然本教程只展示了非特权代币的使用,但Vault文档提供了有关存储和访问秘密的其他方法(https://www.vaultproject.io/docs/secrets/index.html)以及替代身份验证方法(https://www.vaultproject.io/docs/auth/index.htm)的更多信息。

这些指示描述了如何以相当基本的方式部署和使用 Vault,所以请确保阅读 Vault 文档并为您的需求做出适当的配置更改。

这些代币应该使用的具体策略取决于具体的使用情况,但前面的app_token说明了如何创建有限特权代币和策略。

  • 如果 Vault 正在部署作为团队服务的一部分,则为每个团队成员启动 Vault 用解密密钥可以确保 Vault 的存储仅在一个团队成员参与进程时才被解密。
Published At
Categories with 技术
comments powered by Disqus