私密信息管理利器 HashiCorp Vault——部署

版权声明:所有博客文章除特殊声明外均为原创,允许转载,但要求注明出处。

在前面的文章中,我们一直是使用 Vault 服务器的开发模式,但同时也说明了,真正的生产环境中不应该使用开发模式。在本文中,我们就来了解如何将 Vault 部署到生产环境。

存储引擎

在部署之前首先要考虑的一个问题是,我们要如何保存 Vault 的数据。

回忆一下,在开发模式下,服务器输出的信息中有这么一条:

Storage: inmem

这意味着开发模式下,所有信息保存在内存中,服务器关闭数据即消失,这对于生产环境显然是不可接受的。而 Vault 的灵活性在这里又一次得到体现,inmem 是系统支持的存储引擎之一,其他引擎还包括( 完整的列表参考官方文档 ):

引擎 高可用 支持 备注
Azure 社区
CockroachDB 社区
Consul 官方
CouchDB 社区
DynamoDB 社区
Etcd 社区
FileSystem 官方
Google Cloud 社区
In Memory 官方 仅用于开发模式
MySQL 社区
PostgreSQL 社区
Cassandra 社区
S3 社区
Swift 社区
Zookeeper 社区

上表中: * 高可用表示该引擎是否能够配置成集群,来保证数据的高可用。该特性很大程度上是引擎自身的特点决定的,而和 Vault 没有太大关系。 * 支持度表示哪些引擎是官方维护的,哪些是由社区贡献的。理论上来说,官方的引擎表现应该更好一些。

在官方的示例中使用了 Consul 作为存储引擎(同是 HashiCorp 的同门兄弟嘛)。但我在这里不希望把问题搞复杂,因此在后续的操作中,将使用最容易配置的引擎:本地文件系统(File System)。

服务器配置

存储引擎已经决定了,现在我们要创建一个服务器配置文件,服务器将根据该配置决定如何启动。和授权策略(Policy)类似,服务器配置也是使用 HCL 语言编写的,目前我们保持简单,只生成必要的信息:存储引擎和侦听地址。

storage "file" {
    path = "/var/opt/vault"
}

listener "tcp" {
    address = "127.0.0.1:8200"
    tls_disable = 1
}

当然,你需要保证对 path 指定的路径有足够的读写权限。如果担心文件有问题的话,可以运行 vault policy fmt server.hcl 检查一下。

网络配置中的 tls_disable 指定不使用 TLS,这时数据传输是明文的,安全性不够高。如果需要使用 TLS 以加强安全性的话,那么还需要在这里配置证书,详细的内容请参考 tcp 配置

启动服务

现在,我们根据上面创建的配置文件启动服务:

# vault server -config=server.hcl
==> Vault server configuration:

                     Cgo: disabled
              Listener 1: tcp (addr: "127.0.0.1:8200", cluster address: "127.0.0.1:8201", tls: "disabled")
               Log Level: info
                   Mlock: supported: true, enabled: true
                 Storage: file
                 Version: Vault v0.9.3
             Version Sha: 5acd6a21d5a69ab49d0f7c0bf540123a9b2c696d

==> Vault server started! Log data will stream in below:

说明:在某些系统上启动服务器可能会遇到无法使用 mlock 的提示。如果遇到此问题的话,请按如下步骤解决: * 如果仅仅是 warning,服务器仍然可以继续运行的话,那么可以忽略这个提示; * 如果你是以普通用户运行服务器的话,那么最好是换用 root 身份启动服务; * 要是上述方法都不行的话,那么请按照 这里的配置 禁用 mlock。

现在,服务器已经启动成功,但并没有 Root Token 可用。如果候马上去尝试读写数据的话,会发现这样的错误:

vault write secret/hello name=world
Error writing data to secret/hello: Error making API request.
URL: PUT http://127.0.0.1:8200/v1/secret/hello
Code: 503. Errors:
* Vault is sealed

错误信息提示我们 Vault 被密封(Sealed)了,这是什么意思呢?

解封 Vault

Vault 对于数据保护是非常重视的。这体现在服务器启动后,并不能马上访问其数据,而必须经过一个解封(Unseal)的动作。为了保证不是任何人都可以解封服务器,Vault 又规定:对于全新启动的服务,必须经过一个初始化的过程(Initialize),初始化过程中会生成 Unseal Key, 以后必须使用 Unseal Key 来解封服务器。为了进一步加强安全性,Vault 甚至还规定,默认情况下需要至少 3 个 Unseal Key 才能解封服务器。这有点像民主投票的意思了:如果某个用户是恶意的,那么单凭他自己无法访问服务器,还必须经过其他 2 个人的同意,服务器才能开启。

这个过程的确是设计得相当安全,不过相应的服务器的初始化过程也比较复杂。我们来一步一步完成这个操作。

首先我们需要执行 operator 命令来进行初始化。注意初始化只能对新的服务器执行一次,当服务器上已经有数据以后,就不允许再执行这个动作了。

$ vault operator init
Unseal Key 1: /bEBj01yMkDZgYtwzWczC+m8tclpl/7TPoxPBAz5FToE
Unseal Key 2: VDEb4gFwllgSMEOKWx1DZwut9atdY3PyLzM/YCK2Cbo6
Unseal Key 3: WAd8skYyTp8+Iybq/Mp8WDrKb0QhK/xvqcl7u4Rha32e
Unseal Key 4: OZI2i0v1yhf7hF8j1p/AUui0oTQ7cQjDLKF6QnE9cs0U
Unseal Key 5: OoF3fyXH2lkcuu1Si2UQbXaGvZp0gr/cJkUnt6N2O9Yh

Initial Root Token: 444b8cb7-e58d-9e57-076a-fe0763f06248

Vault initialized with 5 key shares an a key threshold of 3. Please securely
distributed the key shares printed above. When the Vault is re-sealed,
restarted, or stopped, you must supply at least 3 of these keys to unseal it
before it can start servicing requests.

Vault does not store the generated master key. Without at least 3 key to
reconstruct the master key, Vault will remain permanently sealed!

It is possible to generate new unseal keys, provided you have a quorum of
existing unseal keys shares. See "vault rekey" for more information.

强调:这里的信息非常重要!! 初始化动作为我们生成了 5 个 Unseal key,此外还有默认的 Root Token。请务必马上把这些信息记录到安全的地方,因为以后你就没有机会再看到它们了。按照 Vault 的设计,理想情况下我们应该把 5 个 Key 分配给不同的人,需要超过一半的人以上同意,我们才能解封服务器(集齐7颗龙珠召唤神龙?)很多小企业未必有这么多人可以授权,那么我们把所有 Unseal Key 一起管理也是允许的,当然这样安全等级就没有那么高了。

接下来我们执行解封(Unseal):

$ vault operator unseal
Unseal Key (will be hidden): 
Key                Value
---                -----
Seal Type          shamir
Sealed             true
Total Shares       5
Threshold          3
Unseal Progress    1/3
Unseal Nonce       a8dd07a3-2fd3-19b6-d61d-b7687ffbcdcd
Version            0.9.3
HA Enabled         true
HA Mode            sealed

请按照提示粘贴一个 Unseal key 进去。输出信息告诉我们,目前解封进度只执行了1/3,我们还需要另外 2 个 Key 才能完成解封。

继续上述操作,每次选择另一个 Unseal key(已使用的 Key 再次使用无效),3 次以后服务器将被解封:

$ vault operator unseal
Unseal Key (will be hidden): 
Key             Value
---             -----
Seal Type       shamir
Sealed          false
Total Shares    5
Threshold       3
Version         0.9.3
Cluster Name    vault-cluster-5e474aa3
Cluster ID      8430f6d7-8176-229f-c6be-5ac06107a427
HA Enabled      false

只要看到 Sealed=false,说明解封已经完成了。接下来我们可以用 Root token 执行一系列操作了,当然更合理的做法是按照 上一篇文章 的做法,先分配用户和权限,再用受限用户执行操作,以便将攻击面降低到最小。

系列文章

到这里,我们的大部分内容已经讲完了。后续文章将讲述如何使用 REST API 访问服务器。