Key / Value —— Version 2
kv 机密引擎用于在 Vault 使用的物理存储中存储任意机密。
键名必须始终是字符串。如果您直接通过命令行编写非字符串类型的值,它们将被转换为字符串。但是,您可以通过从 JSON 文件或使用 HTTP API 写入键值数据来保留非字符串类型的值。
这个机密引擎能够区分 ACL 策略内的 create 和 update 功能之间的区别。还支持 patch 功能,用于表示部分更新,而 update 功能表示完全覆盖。
配置
大部分机密引擎在工作之前必须要先进行配置。这些步骤通常是由系统管理员来完成。
用以下命令启用一个 v2 版本的 kv 机密引擎:
$ vault secrets enable -version=2 kv
或者可以用 kv-v2 作为机密引擎类型:
$ vault secrets enable kv-v2
此外,在运行"dev"模式的测试服务器时,默认会在路径 secret/ 处启用 v2 kv 机密引擎(对于非"dev"服务器,当前为 v1)。可以在多个不同的路径禁用、移动或启用它。 kv 机密引擎在每个挂载点上启用的实例都是隔离且唯一的。
从 Version 1 升级到 Version 2
现有的 Version 1 kv 存储可以通过命令行或 API 升级到 Version 2 kv 存储。这将启动升级过程,将现有的键/值数据升级为版本化的格式。在此过程中将无法访问相关路径。此过程可能需要很长时间,因此提前做好计划。
升级到 Version 2 后,以前用来访问数据的路径将不再适用。您将需要调整用户策略以添加对 Version 2 路径的访问,如下面的 ACL 规则部分所述。同样,一旦升级到 Version 2,用户/应用程序将需要更新他们与 kv 数据交互的路径。
可以使用下面的命令将 Version 1 升级到 Version 2:
$ vault kv enable-versioning secret/
Success! Tuned the secrets engine at: secret/
或者调用 API:
$ cat payload.json
{
"options": {
"version": "2"
}
}
$ curl \
--header "X-Vault-Token: ..." \
--request POST \
--data @payload.json \
http://127.0.0.1:8200/v1/sys/mounts/secret/tune
ACL 规则
Version 2 kv 存储使用带前缀的 API,这与 Version 1 API 不同。在从 Version 1 kv 升级之前,要更改 ACL 规则。Version 2 API 中的不同路径也可以采用不同的 ACL。
读写 Version 2 数据都要以 data/ 为前缀。以下策略适用于版本 1 kv:
path "secret/dev/team-1/*" {
capabilities = ["create", "update", "read"]
}
到 Version 2 就应该写成:
path "secret/data/dev/team-1/*" {
capabilities = ["create", "update", "read"]
}
数据删除的权限路径也不一样,要让策略授予删除键的最新版本的权限:
path "secret/data/dev/team-1/*" {
capabilities = ["delete"]
}
要让策略允许删除一个键的任意版本:
path "secret/delete/dev/team-1/*" {
capabilities = ["update"]
}
要让策略允许撤销删除数据:
path "secret/undelete/dev/team-1/*" {
capabilities = ["update"]
}
要让策略允许彻底删除一个版本的数据:
path "secret/destroy/dev/team-1/*" {
capabilities = ["update"]
}
要让策略允许列出键:
path "secret/metadata/dev/team-1/*" {
capabilities = ["list"]
}
要让策略允许查询每个版本的元数据:
path "secret/metadata/dev/team-1/*" {
capabilities = ["read"]
}
要让策略允许删除指定键的所有版本和元数据:
path "secret/metadata/dev/team-1/*" {
capabilities = ["delete"]
}
不能为 Version 2 的 kv 存储设置包含 allowed_parameters、 denied_parameters 和 required_parameters 字段的策略。
可用标志
配置完机密引擎后拥有合适权限的 Vault 令牌的用户或者机器就可以用它来读写数据了。kv 机密引擎允许在键值对的值中写入任意数据。
读写任意数据
- 写入数据
$ vault kv put secret/my-secret foo=a bar=b
Key Value
--- -----
created_time 2019-06-19T17:20:22.985303Z
custom_metadata map[bar:123 foo:abc]
deletion_time n/a
destroyed false
version 1
- 读取数据:
$ vault kv get secret/my-secret
====== Metadata ======
Key Value
--- -----
created_time 2019-06-19T17:20:22.985303Z
custom_metadata map[bar:123 foo:abc]
deletion_time n/a
destroyed false
version 1
====== Data ======
Key Value
--- -----
foo a
- 再次向同一键写入新版本的数据,之前的版本还是可以访问的。可以选择传递 -cas 标志来执行 check-and-set 操作。如果设置为
-cas=0,则仅当密钥不存在时才允许写入。如果-cas不为零,则仅当密钥的当前版本与cas参数中指定的版本一致时才允许写入。
$ vault kv put -cas=1 secret/my-secret foo=aa bar=bb
Key Value
--- -----
created_time 2019-06-19T17:22:23.369372Z
custom_metadata map[bar:123 foo:abc]
deletion_time n/a
destroyed false
version 2
- 再读一次就可以得到最新版本的数据:
$ vault kv get secret/my-secret
====== Metadata ======
Key Value
--- -----
created_time 2019-06-19T17:22:23.369372Z
custom_metadata map[bar:123 foo:abc]
deletion_time n/a
destroyed false
version 2
====== Data ======
Key Value
--- -----
foo aa
bar bb
可以使用 vault kv patch 命令实现部分更新。命令将首先尝试发送一个需要 patch ACL 权限的 HTTP PATCH 请求。如果使用的令牌关联的策略中不包含 patch 权限,那么 PATCH 请求将失败。在这种情况下,该命令将读取最新数据,在本地更新后写回,这一系列操作需要在 ACL 中拥有 read 和 update 权限。
可以选择使用 -cas 参数来执行 check-and-set 操作。它只会在一开始的 PATCH 请求中使用。 读取后完整更新的流程将使用读取返回的机密中的 version 值来在后续写入中执行 check-and-set 操作。
$ vault kv patch -cas=2 secret/my-secret bar=bbb
Key Value
--- -----
created_time 2019-06-19T17:23:49.199802Z
custom_metadata map[bar:123 foo:abc]
deletion_time n/a
destroyed false
version 3
vault kv patch命令还支持-method标志,可用于指定是使用 HTTPPATCH还是先读后写。支持的值分别是patch和rw。
使用 patch 方法执行部分更新:
$ vault kv patch -method=patch -cas=2 secret/my-secret bar=bbb
Key Value
--- -----
created_time 2019-06-19T17:23:49.199802Z
custom_metadata map[bar:123 foo:abc]
deletion_time n/a
destroyed false
version 3
使用 rw 方法进行更新:
$ vault kv patch -method=rw secret/my-secret bar=bbb
Key Value
--- -----
created_time 2019-06-19T17:23:49.199802Z
custom_metadata map[bar:123 foo:abc]
deletion_time n/a
destroyed false
version 3
- 部分更新后读取机密会可以从返回的最新版本的数据中看到,只有部分字段发生了变更:
$ vault kv get secret/my-secret
====== Metadata ======
Key Value
--- -----
created_time 2019-06-19T17:23:49.199802Z
custom_metadata map[bar:123 foo:abc]
deletion_time n/a
destroyed false
version 3
====== Data ======
Key Value
--- -----
foo aa
bar bbb
- 可以使用
-version标志查看先前的版本:
$ vault kv get -version=1 secret/my-secret
====== Metadata ======
Key Value
--- -----
created_time 2019-06-19T17:20:22.985303Z
custom_metadata map[bar:123 foo:abc]
deletion_time n/a
destroyed false
version 1
====== Data ======
Key Value
--- -----
foo a
bar b
删除 / 彻底删除(Destroy)数据
删除数据时,普通的 vault kv delete 命令将执行软删除。它将将该版本标记为已删除并填充一个 deletion_time 时间戳。软删除不会从存储中删除底层版本数据,这使我们可以撤销删除版本。 vault kv undelete 命令可以撤销删除版本。
仅当键的版本数超过 max-versions 设置允许的数量时,或使用 vault kv destroy 命令时,才会永久删除版本数据。当使用 destroy 命令时,底层版本数据将被删除,并且键值对的元数据将被标记为已销毁。如果一个版本是通过 max-versions 机制被清理的,那么它的版本元数据也将从键值对中删除。
以下操作可以提供进一步的说明:
- 可以使用
delete命令删除键值对的最新版本,也可以通过-versions标志来删除过去的版本:
$ vault kv delete secret/my-secret
- 可以撤销删除的版本:
$ vault kv undelete -versions=2 secret/my-secret
Success! Data written to: secret/undelete/my-secret
$ vault kv get secret/my-secret
====== Metadata ======
Key Value
--- -----
created_time 2019-06-19T17:23:21.834403Z
custom_metadata map[bar:123 foo:abc]
deletion_time n/a
destroyed false
version 2
====== Data ======
Key Value
--- -----
my-value short-lived-s3cr3t
- 彻底删除一个版本的数据:
$ vault kv destroy -versions=2 secret/my-secret
Success! Data written to: secret/destroy/my-secret
键的元数据
可以使用元数据命令和 API 跟踪键的所有版本和元数据。删除键的元数据将导致该键值对的所有元数据和版本被永久删除。
- 查询一个键的所有元数据和版本:
$ vault kv metadata get secret/my-secret
========== Metadata ==========
Key Value
--- -----
cas_required false
created_time 2019-06-19T17:20:22.985303Z
current_version 2
custom_metadata map[bar:123 foo:abc]
delete_version_after 0s
max_versions 0
oldest_version 0
updated_time 2019-06-19T17:22:23.369372Z
====== Version 1 ======
Key Value
--- -----
created_time 2019-06-19T17:20:22.985303Z
deletion_time n/a
destroyed false
====== Version 2 ======
Key Value
--- -----
created_time 2019-06-19T17:22:23.369372Z
deletion_time n/a
destroyed true
- 可以设置一个键的元数据配置:
$ vault kv metadata put -max-versions 2 -delete-version-after="3h25m19s" secret/my-secret
Success! Data written to: secret/metadata/my-secret
-delete-version-after 设置只对新版本数据有效。下次写入的数据就会应用 -max-versions 的约束:
$ vault kv put secret/my-secret my-value=newer-s3cr3t
Key Value
--- -----
created_time 2019-06-19T17:31:16.662563Z
custom_metadata map[bar:123 foo:abc]
deletion_time 2019-06-19T20:56:35.662563Z
destroyed false
version 4
当一个键的版本超过 -max-versions 设置的限制,旧版本会被清理:
$ vault kv metadata get secret/my-secret
========== Metadata ==========
Key Value
--- -----
cas_required false
created_time 2019-06-19T17:20:22.985303Z
current_version 4
custom_metadata map[bar:123 foo:abc]
delete_version_after 3h25m19s
max_versions 2
oldest_version 3
updated_time 2019-06-19T17:31:16.662563Z
====== Version 3 ======
Key Value
--- -----
created_time 2019-06-19T17:23:21.834403Z
deletion_time n/a
destroyed true
====== Version 4 ======
Key Value
--- -----
created_time 2019-06-19T17:31:16.662563Z
deletion_time 2019-06-19T20:56:35.662563Z
destroyed false
机密键值对的元数据可以包含用于描述机密的自定义元数据。数据将存储为字符串到字符串的键值对。如果设置了 -custom-metadata 标志,则 custom_metadata 的值将被覆盖。 可以重复使用 -custom-metadata 标志添加多个键值对:
$ vault kv metadata put -custom-metadata=foo=abc -custom-metadata=bar=123 secret/my-secret
- 永久删除一个键的所有元数据和版本:
$ vault kv metadata delete secret/my-secret
Success! Data deleted (if it existed) at: secret/metadata/my-secret