参考资料
vault学习博客(入门推荐)
HashiCorp Vault介绍(入门推荐)
1、Vault是什么
vault是一个密码/证书集中式管理工具,通过HTTP-API对外提供统一的密码访问入口,并且提供权限控制以及详细的日志审计功能。
一个系统可能需要访问多个带密码的后端:例如数据库、通过API keys对外部系统进行调用,面向服务的架构通信等等。要将众多系统中的用户和权限对应起来已经非常困难,加上提供密钥滚动功能、安全的存储后端还要有详细的审计日志,自定义解决方案几乎不太可能。这也就是vault存在的意义。
通俗来讲,就是一般来说,我们对数据的加密都是在后端直接进行处理,这样的话,首先是密钥的管理不安全,权限的管理也不清楚,如果密钥滚动升级也不方便,所以我们可以调用Vault进行解耦,讲数据的加密等操作直接交给Vault,我们后端需要加密和解密就直接交给Vault服务处理就行。
2、为什么要使用Vault
在企业级应用开发过程中,团队每时每刻都需要管理各种各样的私密信息,从个人的登陆密码、到生产环境的SSH Key以及数据库登录信息、API认证信息等。通常的做法是将这些秘密信息保存在某个文件中,并且放置到git之类的源代码管理工具中。个人和应用可以通过拉取仓库来访问这些信息。但这种方式弊端很多,比如跨团队分享存在安全隐患、文件格式难以维护、私密信息难以回收等。
尤其是在微服务如此风靡的今天,如何让开发者添加私密信息、应用程序能轻松的获取私密信息、采用不同策略更新私密信息、适时回收私密信息等变得越来越关键。所以企业需要一套统一的接口来处理私密信息的方方面面,而HashiCorp Vault就是这样的一款工具。
3、Vault的特性
(1)安全的存储后端:任意的键值对密码都能存储在vault。vault在把数据写入存储后端之前会先将数据加密,所以即使你直接读取存储后端数据也无法拿到真正的数据。vault的存储后端可以是文件、Consul、etcd等等。
(2)动态密码生成:vault能够按需生成某些后端的密码,例如:AWS、SQL数据库等等。例如当一个应用需要访问AWS的S3 bucket,应用向vault请求访问S3 bucket的证书,vault能按需生成一个指定权限的AWS密钥,并且能够根据租期自动销毁这个密钥。
(3)数据加密:vault可以在不对数据存储的情况下,对数据进行加密和解密。安全团队只需定义好加密方法,开发将加密后的数据存储在例如SQL之类的后端即可,而无需设计自己的加密方式。
(4)租期和续租:在vualt里面,全部的密码都可以跟租期联系起来。在租期结束时,vault会自动销毁对应的密码。客户端能够通过renew-API进行续租。
(5) 销毁:vault本身支持对密码进行销毁,不仅支持销毁单个密码,还支持销毁与之关联的密码。比如指定某个用户读取的全部密码,或者特定类型的密码。销毁功能能够在密码被泄露的时候辅助锁定系统。
(6)存储私密信息:不仅可以存放现有的私密信息,还可以动态生成用于管理第三方资源的私密信息。所有存放的数据都是加密的,任何动态生成的私密信息都有租期,并且到期会自动回收。
(7)滚动更新密钥:用户可以随时更新存放的私密信息。Vault提供了加密即服务(encryption-as-a-service)的功能,可以随时将密钥滚动到新的密钥版本,同时保留对使用过去密钥版本加密的值进行解密的能力。 对于动态生成的秘密,可配置的最大租赁寿命确保密钥滚动易于实施。
(8)审计日志:保管库存储所有经过身份验证的客户端交互的详细审核日志:身份验证,令牌创建,私密信息访问,私密信息撤销等。 可以将审核日志发送到多个后端以确保冗余副本。
4、Vault的使用场景
(1) 作为集中存储各个服务器账号密码的服务器。目前我们有服务器需要访问到有密码的后端的时候,有几种方案:
- export到环境变量
- 写死到代码里面
- 上线的时候使用自动化工具对变量进行替换
第一种方案带来的问题是使用麻烦,后两种方案带来的问题是维护和变更麻烦。比如DB密码泄露,需要修改密码,首先DBA修改密码,然后通知到应用,应用再做代码上的变更。如果使用vault的话,DBA只要在vault上面修改好密码之后通知应用重新从vault拉取最新密码就行了。
(2)为每一个操作单位动态分配账号
比如过去我们想要对某些敏感操作进行审计,但是由于生成账号比较麻烦,所以存在公用账号的情况。vault支持为某些后端动态生成账号的功能,比如SQL,当某个应用向vault请求账号密码的时候,vault能够为每次请求生成一个独一无二的SQL账号密码。
(3) 作为证书服务器
vault能够作为CA服务器,根据请求信息自动颁发证书。并且提供在线CA和CRL的功能。不过目前只能在vault里面新生成ROOT-CA,不能导入原有的ROOT-CA。
(4)作为OAUTH服务器
vault支持多种认证后端,比如github、kubernetes、账号密码等等。vault能够将这些账号关联成一个用户,在用户认证之后返回一个token供用户使用。
5、安装一个简单的Vault服务(Windows下的开发模式)
1、下载Vault可以从 Vault官网 下载最新版本,或者直接下载1.9.3版本:https://releases.hashicorp.com/vault/1.9.3/vault_1.9.3_windows_amd64.zip。
2、下载完成之后,解压,会发现包中只有一个Vault.exe。
3、直接Shift+右键打开PowerShell,输入且回车
.\vault --version
可以看到Vault的版本
4、如果输入且回车
.\vault
的话,会显示Vault的基本命令。
5、启动Vault服务
Vault是服务器-客户端的架构,但所有功能都包含在一个单一的可执行文件中。为了运行Vault,我们需要并发地开两个终端窗口:一个运行服务器,一个运行客户端。
为了方便本地开发与测试,Vault 服务器提供了开发模式。开发模式下不需要额外的配置,所有数据保存在内存中,从命令行可以直接访问。当然,相应的结果是开发模式下的安全性很差,可以不受限制的访问几乎任何数据,所以开发模式仅供学习和本地测试使用,生产环境中绝对不要使用。
使用如下命令,用开发模式启动服务器:
.\vault server -dev
你可以看到服务器输出了相当多的内容。其中,我们重点关注下列信息:
- 服务器侦听地址为 127.0.0.1:8200 (还有一个端口 8201 用于集群使用,目前我们不关注);
- 数据存储使用内存引擎(inmem)。这意味着开发模式下所有数据在关闭服务器后都不会保留;
- 命令行客户端访问服务器,需要首先设置环境变量(VAULT_ADDR);
- Unseal Key 在生产模式下很重要,但是开发环境下暂时用不到;
Root Token 值得重点说明一下。Vault 提供多种验证/授权客户端的机制,其中 Token 是默认的验证手段。无论开发还是生产环境,服务器启动时都会生成一个 Root Token,该 Token 相当于 Linux 系统中的 root user,具有最高的访问权限。使用 Root Token 登录系统的用户可以生成另外的 Token,并且为这些 Token 设置特定的访问权限。这就是 Vault 的认证/授权机制。在开发模式下,用户默认是使用 Root Token 登录的,当然也可以在分配新的 Token 之后,使用新 Token 重新登录。后面我们还会具体介绍 Auth Token 的管理过程。
现在,你应该把 Root Token 记录在方便访问的地方,因为日志多了以后,再回头找这个信息就困难了。
按照说明,我们新建一个单独的终端运行客户端:
首先我们需要设置环境变量,由上面的说明可以看到:
如果是PowerShell的话,就输入:
$env:VAULT_ADDR="http://127.0.0.1:8200"
如果是CMD的话,就输入
set VAULT_ADDR=http://127.0.0.1:8200
我们这里是PowerShell,所以输入前者
然后这样我们一个简单的Vault服务器就搭好了,可以进行简单的读写了。
6、读写数据
服务器和客户端均已就位,接下来我们可以往里面读写数据了:
PS C:\Users\vault_1.9.3_windows_amd64> ./vault kv put secret/hello value=world
Key Value
--- -----
created_time 2022-02-23T07:13:15.702428Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
PS C:\Users\vault_1.9.3_windows_amd64> ./vault kv put secret/hello excited=yes name=user
Key Value
--- -----
created_time 2022-02-23T07:14:42.9761421Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 2
PS C:\Users\vault_1.9.3_windows_amd64> ./vault kv get secret/hello
======= Metadata =======
Key Value
--- -----
created_time 2022-02-23T07:14:42.9761421Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 2
===== Data =====
Key Value
--- -----
excited yes
name user
读写数据使用kv get/kv put命令。参数 secret/hello这是一个路径(Path)。Vault 中用 Path 区分不同数据的存放位置。一个 Path 下可以包含多个键值对,但需要注意的是 kv put命令是覆盖式的而不是追加式的,所以第一条命令写入的值会被后来的所覆盖,因此你必须确保在同一个命令中一次性写入所有的内容。
kv get命令读出了刚才写入的内容。我们还可以将数据输出为 Json 格式,以便观察更详细的信息,同时也方便支持 Json 格式的库读取:
PS C:\Users\vault_1.9.3_windows_amd64> ./vault kv get -format=json secret/hello
{
"request_id": "bb05f2a4-9752-f577-ca51-33d7584fd4a2",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"data": {
"excited": "yes",
"name": "user"
},
"metadata": {
"created_time": "2022-02-23T07:14:42.9761421Z",
"custom_metadata": null,
"deletion_time": "",
"destroyed": false,
"version": 2
}
},
"warnings": null
}
我们设置的值在 Json 数据的 data 节点下。还可以看到,刚才输出的 refresh_interval 实际上是该数据租期(Lease)的一种表达形式。租期是 Vault 用来表示私密数据有效期的一个概念。租期的内部时间(lease_duration)是用秒来记录的,你可以自己换算一下。由于该数据是不可更新(Renewable)的,因此 lease_id 为空。
如果我们不再需要该数据,可以用 delete 命令删除它:
PS C:\Users\LENOVO\Downloads\vault_1.9.3_windows_amd64> ./vault kv delete secret/hello
Success! Data deleted (if it existed) at: secret/hello
PS C:\Users\LENOVO\Downloads\vault_1.9.3_windows_amd64> ./vault kv get secret/hello
======= Metadata =======
Key Value
--- -----
created_time 2022-02-23T07:14:42.9761421Z
custom_metadata <nil>
deletion_time 2022-02-23T07:21:30.3323252Z
destroyed false
version 2
可以看到没有数据了。
在上述例子中,我们使用了 secret/hello 路径,这个路径并不是随意指定的。默认情况下,你只能把私密数据保存在以 secret/ 为前缀的路径下,否则会出现下面的错误信息:
PS C:\Users\LENOVO\Downloads\vault_1.9.3_windows_amd64> ./vault kv put foo/bar a=b
Error making API request.
URL: GET http://127.0.0.1:8200/v1/sys/internal/ui/mounts/foo/bar
Code: 403. Errors:
* preflight capability check returned 403, please ensure client's policies grant access to
path "foo/bar/"
从出错信息可以发现,Vault 服务器/客户端之间实际上是 RESTful 形式的 HTTP 通信。
7、其他补充
关于存储
vault存储后端不受信任,用于持久存储加密数据,启动vault时,必须为其提供存储后端。支持的存储有:
关于解封(unsealed)
启动vault时,vault处于密封状态(sealed),必须需要一个解密(unseal)的过程,初始化vault时,他会生成一个加密密钥(Encryption Key),用于保护所有数据,这个密钥由一个主密钥(Master Key)保护着,默认情况下,Vault用一种成为Shamir的秘密共享算法,将其分成五份Key Shares,其中如果有三份或以上的Key Shares,那么就可以解密主密钥,然后再解封Vault。
这里的五份主密钥,在实际的工作中为了最大安全化,一般是在五个不同的人身上,可以设置指定Key Shares的份数和解密所需要的份数,或者也可以直接禁用这种形式,使用单独的主密钥都是可以的。
常用指令
vault server -dev
vault status
vault operator init
vault operator unseal
vault operator seal
vault kv put a/b/c/d k=v
vault kv get a/b/c/d
vault read a/b/c/d
vault write a/b/c/d k=v
vault policy list
vault secrets list
vault policy read default
vault policy write admin admin-policy.hcl
vault secrets enable -paht=mypaht kv
vault print token
vault status
vault vault list a/b/c/
vault token capabilities s.2sHGlAHNj36LpqQ2Zevl20wi sys/auth/approle
vault token create
vault token create -policy="admin"
vault token revoke s.2sHGlAHNj36LpqQ2Zevl20wi
vault login s.2sHGlAHNj36LpqQ2Zevl20wi
vault auth list
vault auth help github
vault auth disable github
vault login -method=github
vault list sys/leases/lookup/database/creds/readonly
vault lease renew database/creds/readonly/IQKUMCTg3M5QTRZ0abmLKjTX
vault lease revoke database/creds/readonly/IQKUMCTg3M5QTRZ0abmLKjTX
vault lease revoke -prefix database/creds/readonly