介绍
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的init系统,其中包括管理系统的服务。 为了将Vault设置为系统服务,我们需要设置以下内容:
- Vault守护程序运行时的系统用户
- 用于存储Vault信息的数据目录
- 保管库的配置文件
- 系统单元文件本身。
注意 :在本教程中,我们使用文件系统后端将加密机密存储在本地文件系统的/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
将以下内容粘贴到该文件中,并确保替换您的域名:
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"
}
此配置文件指示保管库将加密的秘密存储在磁盘上的/var/lib/vault
,并指示Vault应使用Let's Encrypt教程生成的证书通过HTTPS监听连接。
保存并关闭文件,然后通过只允许Vault用户读取它来保护Vault配置文件的权限。
sudo chown vault:vault /etc/vault.hcl
sudo chmod 640 /etc/vault.hcl
接下来,要让Systemd管理持久保管库守护程序,请在/etc/systemd/system/vault.service
创建一个单元文件 。
sudo nano /etc/systemd/system/vault.service
将以下内容复制并粘贴到文件中。 这允许Vault作为持久系统服务守护程序在后台运行。
[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
配置文件。 -
User
和Group
,用于控制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}
然后将保险库用户添加到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
命令现在可以与守护进程进行通信。 请注意,为了正确验证HTTPS证书,定义实际主机名而不是简单的localhost
或127.0.0.1
是必要的。
通过检查库的状态确认库处于未初始化状态。
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在初始化时会公开两个信息,这些信息在任何其他位置都不可用:
- 初始根令牌 。 这相当于您的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中的特定路径。
第4步 - 读写秘密
在Vault文档中列举了几个秘密后端 ,但对于此示例,我们将使用通用秘密后端 。 此后端在Vault中存储简单的键/值对。
首先,将先前生成的根令牌保存到shell变量中以便于使用。
root_token=your_root_token_here
首先,将值写入Vault中的路径。
VAULT_TOKEN=$root_token vault write secret/message value=mypassword
在这个命令中, secret/
前缀表示我们正在写入安装在secret
路径上的generic
后端,并且我们正在使用值mypassword
将路径message
的键值存储。 我们使用具有超级用户权限的根令牌来写入通用密码。
在现实世界中,您可以存储API密钥或外部工具可以使用的密码等值。 虽然您可以使用根令牌再次读取秘密值,但它是说明性的,可以生成一个权限较低的令牌,并对我们的单个秘密拥有只读权限。
创建一个名为policy.hcl
的文件。
nano policy.hcl
使用以下Vault策略填充文件,该策略定义工作目录中对秘密路径的只读访问权限:
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
这证实了权限较低的应用令牌不能执行任何破坏性行为或访问除了其保险库政策中明确规定的其他秘密值。
结论
在本文中,您已经在Ubuntu 16.04上安装,配置并部署了Vault。 尽管本教程仅演示了如何使用非特权令牌,但Vault文档还提供了有关存储和访问机密以及替代验证方法的 其他方法的更多信息。
这些说明概述了如何以相当基本的方式部署和使用Vault,因此请务必阅读Vault文档并针对您的需求进行适当的配置更改。 一些生产就绪的更改包括:
为日常使用生成权限较低的令牌。 这些令牌应使用的特定策略取决于特定用例,但前面的
app_token
说明了如何创建有限特权令牌和策略。如果将Vault作为团队服务的一部分进行部署,则使用每个团队成员的开封密钥对Vault进行初始化可以确保仅当多个团队成员参与流程时才会解密Vault的存储。