介绍
Vault是一款机密信息管理工具,类似PKI管理工具。
支持KV密码引擎保存键值对信息,可以把密匙保存在json键值对里。
支持数据库或云服务密码引擎,用来对数据库、SSH、云服务等生成动态密码,在隐藏原有密码的基础上可以设置生成动态密码,设置动态密码的有效期从而对每一对分发的动态密码做管理,类似浏览器自动生成密码的功能,即使被第三方盗取了也没关系,这种用到的情况比较少,可能在需要给其他供应商临时用用数据库的时候才有用。
支持PKI证书ca证书的生成和cert证书的分发。
Vault可以配置不同的策略(policy),来生成策略里不同权限的token,每次请求vault的时候表头都必须带着包含此接口权限的token,所以可以通过不同的policy生成不同权限的token来保证谁能访问哪些数据,他的强大之处并不在于保存了这些机密信息,更重要的是可以对这些机密信息的访问权限进行管控。
Vault默认把存储的机密信息存在磁盘文件里,在第一次启动Vault的时候需要先进行初始化操作,此时会生成几个key,和一个rootToken,那些key就是用来解封存储信息的,而这些key是在初始化的时候随机生成的,所以在Vault初始化的时候一定要保存好生成的key,只有通过这些key解封vault后,才可以访问到里面存储的机密信息。所以就连vault本身也不知道存储的信息究竟是什么,大大增强了安全性,但是千万不要把这些key搞丢了,不然有可能会永远失去这些机密信息的访问权限。
初始化的时候默认会生成5个key,解封的时候默认验证其中的随便三个key,全部对的上才可以解封vault里面的机密信息,这个key的数量和验证的次数在初始化的时候是可以通过加参数的方式自行更改的,在极端情况下,生成的这些key可以通过不同的人保管,每人保管一个key,比如,生成5个key,通过不同的5个人分别保管,这样当服务停掉再次启动服务时,只有这五个人中的至少三个人把拥有的key拿出来才可以解封vault里面存储的机密信息,是不是有点像集齐七龙珠召唤神龙的感觉。看来龙珠很早就知道这种加密方法了啊,小时候居然意识不到,实在惭愧~
github地址:https://hub.fastgit.org/hashicorp/vault
官网: https://www.vaultproject.io
开发文档说明:https://www.vaultproject.io/docs/
官网快速入门教程:HashiCorp's Learn Platform
官方文档中http api:https://www.vaultproject.io/api-docs
Vault可以通过CLI(linux命令行)、HTTP API来操作访问,实际上CLI底层也是做了HTTP API转换然后去请求vault服务器的,对于java程序员来说,可以做一个前置java服务通过HTTP API来统一访问vault,会比较方便。
安装(ubuntu为例)
vault下载地址:https://www.vaultproject.io/downloads
下载解压后会有一个vault文件,把安装路径加入环境变量
如果以前存在PATH路径则多个路径之间用:分隔,如安装路径是/root/vault/vault
export PATH=$PATH:/root/vault/
此时执行vault命令就可以看到以下信息说明安装成功了,是不是很简单。
zhaohy@zhaohy-Lenovo-Legion-R7000-2020:/usr/share$ vault
Usage: vault [args]
Common commands:
read Read data and retrieves secrets
write Write data, configuration, and secrets
delete Delete secrets and configuration
list List data or secrets
login Authenticate locally
agent Start a Vault agent
server Start a Vault server
status Print seal and HA status
unwrap Unwrap a wrapped secret
Other commands:
audit Interact with audit devices
auth Interact with auth methods
debug Runs the debug command
kv Interact with Vault's Key-Value storage
lease Interact with leases
monitor Stream log messages from a Vault server
namespace Interact with namespaces
operator Perform operator-specific tasks
path-help Retrieve API help for paths
plugin Interact with Vault plugins and catalog
policy Interact with policies
print Prints runtime configurations
secrets Interact with secrets engines
ssh Initiate an SSH session
token Interact with tokens
启动并初始化
在vault安装路径新建config.hcl
ui = true
disable_mlock = true
storage "raft" {
path = "/home/zhaohy/myspace/profiles/vault/data"
node_id = "node1"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = "true"
}
api_addr = "http://127.0.0.1:8200"
cluster_addr = "https://127.0.0.1:8201"
上面存储路径定义的是/home/zhaohy/myspace/profiles/vault/data,所以要保证data这个文件夹存在,没有的话在/home/zhaohy/myspace/profiles/vault/文件夹下新建,也可以指定其他位置。
启动命令:
vault server -config=config.hcl
设置环境变量VAULT_ADDR
export VAULT_ADDR='http://127.0.0.1:8200'
第一次启动的时候要先初始化,后面再启动就不用再初始化了
vault operator init
初始化之后会得到5个key和一个root token,保存这些信息。如:
zhaohy@zhaohy-Lenovo-Legion-R7000-2020:~/myspace/profiles/vault$ vault operator init
Unseal Key 1: Nmvwu+36tZANTWBdLX+eFWK9PXRC8XN2B+6UBx1hFQ5m
Unseal Key 2: rFXCziQkyPPCROEAFzlCrGNKy3JZPJn6L8E1zpxRbT/j
Unseal Key 3: ALVkUiR4aVdbNrETUpaPqOUvaBUMl8gTAX6s6caZcy/+
Unseal Key 4: 2tl9Fl6fXwefluhyHbxpNIbYNOuSmxMwIFwDUEsqJFC6
Unseal Key 5: m58KajrUksOz0xeoglS6z/8pMLxr0yVsXeYnhQ9Eux3J
Initial Root Token: s.Xu7quPen8GBxjhVUtI1lq1XD
Vault initialized with 5 key shares and a key threshold of 3. Please securely
distribute 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 operator rekey" for more information.
解封
默认启动是密封的,要先解封才能使用
用刚刚启动得到的5个key和token解封,默认会解封三次,用其中的随便3个key
此时访问http://127.0.0.1:8200/ui可以在网页上请求http api的形式解封,也可以用CLI命令解封
如上图,输入5个key中的随便一个,连续解封三次(三次的key不能相同)
或者命令行解封三次也是同样的效果
vault operator unseal
登录
可以用刚刚的token登录,也可以在root下面生成新的token来登录(继承root token的权限,后面再说)
vault login
也可以在http界面上输入登录
停止服务命令
ps aux | grep "vault server" | grep -v grep | awk '{print $2}' | xargs kill
登录之后我们就可以看到http界面上的主页界面:
默认会有一个cubbyhole的kv密码引擎
可以在界面上在里面新建path和键值对(通过http api的形式)
当然这些都可以通过CLI命令行或者HTTP API的形式进行和vault服务器交互
policy默认会有default和root两个策略,root有全部的权限。
可以新建policy,配置不同的路径策略,就可以通过这些policy生成不同权限的token
新建policy以及生成token的方法可以去https://www.vaultproject.io/api-docs里查看http api如何使用,还是比较简单的。
我在postman上总结了一些常用api用法例子:
导出的postman请求json如下:
{
"info": {
"_postman_id": "308e9ecc-2a29-466e-8732-2411e39b510d",
"name": "vault",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "初始化",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\"secret_shares\": 1, \"secret_threshold\": 1}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://127.0.0.1:8200/v1/sys/init",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"sys",
"init"
]
}
},
"response": []
},
{
"name": "根据序列号查询crt证书",
"protocolProfileBehavior": {
"disableBodyPruning": true
},
"request": {
"method": "GET",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://127.0.0.1:8200/v1/pki/cert/27-b4-0f-19-43-61-3c-70-16-b5-3b-60-5d-29-7b-99-f7-b0-30-2f",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"pki",
"cert",
"27-b4-0f-19-43-61-3c-70-16-b5-3b-60-5d-29-7b-99-f7-b0-30-2f"
]
}
},
"response": []
},
{
"name": "查询证书cert序列号",
"request": {
"method": "LIST",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"url": {
"raw": "http://127.0.0.1:8200/v1/pki/certs",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"pki",
"certs"
]
}
},
"response": []
},
{
"name": "新建token",
"request": {
"method": "POST",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\"period\":\"240\"}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://127.0.0.1:8200/v1/auth/token/create",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"auth",
"token",
"create"
]
}
},
"response": [
{
"name": "新建token",
"originalRequest": {
"method": "POST",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\"period\":\"3600\",\"policies\":[\"test-policy\"]}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://127.0.0.1:8200/v1/auth/token/create",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"auth",
"token",
"create"
]
}
},
"status": "OK",
"code": 200,
"_postman_previewlanguage": "json",
"header": [
{
"key": "Cache-Control",
"value": "no-store"
},
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Date",
"value": "Thu, 15 Apr 2021 09:54:30 GMT"
},
{
"key": "Content-Length",
"value": "429"
}
],
"cookie": [],
"body": "{\n \"request_id\": \"7ede45aa-e0c5-0f65-ee0b-04fa06cec028\",\n \"lease_id\": \"\",\n \"renewable\": false,\n \"lease_duration\": 0,\n \"data\": null,\n \"wrap_info\": null,\n \"warnings\": null,\n \"auth\": {\n \"client_token\": \"s.3luOj8yNzW4nwvMIMY2SIfQK\",\n \"accessor\": \"6I5GVJtoqqOEqNc6wtd67BlT\",\n \"policies\": [\n \"default\",\n \"test-policy\"\n ],\n \"token_policies\": [\n \"default\",\n \"test-policy\"\n ],\n \"metadata\": null,\n \"lease_duration\": 3600,\n \"renewable\": true,\n \"entity_id\": \"\",\n \"token_type\": \"service\",\n \"orphan\": false\n }\n}"
}
]
},
{
"name": "查看自己token的配置",
"protocolProfileBehavior": {
"disableBodyPruning": true
},
"request": {
"method": "GET",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://127.0.0.1:8200/v1/auth/token/lookup-self",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"auth",
"token",
"lookup-self"
]
}
},
"response": [
{
"name": "查看自己token的配置",
"originalRequest": {
"method": "GET",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://127.0.0.1:8200/v1/auth/token/lookup-self",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"auth",
"token",
"lookup-self"
]
}
},
"status": "OK",
"code": 200,
"_postman_previewlanguage": "json",
"header": [
{
"key": "Cache-Control",
"value": "no-store"
},
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Date",
"value": "Thu, 15 Apr 2021 09:08:22 GMT"
},
{
"key": "Content-Length",
"value": "461"
}
],
"cookie": [],
"body": "{\n \"request_id\": \"77d2c894-ceb0-4320-7947-801805da557b\",\n \"lease_id\": \"\",\n \"renewable\": false,\n \"lease_duration\": 0,\n \"data\": {\n \"accessor\": \"j8Px6MoDMppeWcZz2fJlDnyg\",\n \"creation_time\": 1618051941,\n \"creation_ttl\": 0,\n \"display_name\": \"root\",\n \"entity_id\": \"\",\n \"expire_time\": null,\n \"explicit_max_ttl\": 0,\n \"id\": \"s.M8UXMFH6p5KUS6S5Ta5ruY6X\",\n \"meta\": null,\n \"num_uses\": 0,\n \"orphan\": true,\n \"path\": \"auth/token/root\",\n \"policies\": [\n \"root\"\n ],\n \"ttl\": 0,\n \"type\": \"service\"\n },\n \"wrap_info\": null,\n \"warnings\": null,\n \"auth\": null\n}"
}
]
},
{
"name": "查看指定token的配置",
"request": {
"method": "POST",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\"token\":\"s.8hRkajciaXbkOQYzMQV1RIhH\"}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://127.0.0.1:8200/v1/auth/token/lookup",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"auth",
"token",
"lookup"
]
}
},
"response": []
},
{
"name": "续订指定token",
"request": {
"method": "POST",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\r\n \"token\": \"s.PbftZ3fDiHCtcnAFZftmZYzb\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://127.0.0.1:8200/v1/auth/token/renew",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"auth",
"token",
"renew"
]
}
},
"response": []
},
{
"name": "吊销token",
"request": {
"method": "POST",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\r\n \"token\": \"s.8hRkajciaXbkOQYzMQV1RIhH\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://127.0.0.1:8200/v1/auth/token/revoke",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"auth",
"token",
"revoke"
]
}
},
"response": [
{
"name": "吊销token",
"originalRequest": {
"method": "POST",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\r\n \"token\": \"s.8hRkajciaXbkOQYzMQV1RIhH\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://127.0.0.1:8200/v1/auth/token/revoke",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"auth",
"token",
"revoke"
]
}
},
"status": "No Content",
"code": 204,
"_postman_previewlanguage": "json",
"header": [
{
"key": "Cache-Control",
"value": "no-store"
},
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Date",
"value": "Fri, 16 Apr 2021 06:00:57 GMT"
}
],
"cookie": [],
"body": null
}
]
},
{
"name": "生成cert",
"request": {
"method": "POST",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\r\n \"common_name\": \"www.example.com\",\r\n \"ttl\":\"30\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://127.0.0.1:8200/v1/pki/issue/test.com",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"pki",
"issue",
"test.com"
]
}
},
"response": []
},
{
"name": "根据cert编号获取cert",
"request": {
"method": "GET",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"url": {
"raw": "http://127.0.0.1:8200/v1/pki/cert/09-7c-e7-f0-7b-c9-87-57-6a-26-3c-46-a1-41-90-ec-95-e7-5e-54",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"pki",
"cert",
"09-7c-e7-f0-7b-c9-87-57-6a-26-3c-46-a1-41-90-ec-95-e7-5e-54"
]
}
},
"response": []
},
{
"name": "吊销cert",
"request": {
"method": "POST",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\r\n \"serial_number\": \"09-7c-e7-f0-7b-c9-87-57-6a-26-3c-46-a1-41-90-ec-95-e7-5e-54\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://127.0.0.1:8200/v1/pki/revoke",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"pki",
"revoke"
]
}
},
"response": []
},
{
"name": "新增引擎",
"request": {
"method": "PUT",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\"path\":\"secret\",\"type\":\"kv\",\"config\":{},\"options\":{\"version\":1},\"generate_signing_key\":true}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://127.0.0.1:8200/v1/sys/mounts/secret",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"sys",
"mounts",
"secret"
]
}
},
"response": [
{
"name": "新增kv引擎",
"originalRequest": {
"method": "PUT",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\"path\":\"secret\",\"type\":\"kv\",\"config\":{},\"options\":{\"version\":1},\"generate_signing_key\":true}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://127.0.0.1:8200/v1/sys/mounts/secret",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"sys",
"mounts",
"secret"
]
}
},
"status": "No Content",
"code": 204,
"_postman_previewlanguage": "json",
"header": [
{
"key": "Cache-Control",
"value": "no-store"
},
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Date",
"value": "Thu, 15 Apr 2021 09:03:53 GMT"
}
],
"cookie": [],
"body": null
}
]
},
{
"name": "吊销引擎",
"request": {
"method": "DELETE",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"url": {
"raw": "http://127.0.0.1:8200/v1/sys/mounts/secret",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"sys",
"mounts",
"secret"
]
}
},
"response": [
{
"name": "吊销引擎",
"originalRequest": {
"method": "DELETE",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"url": {
"raw": "http://127.0.0.1:8200/v1/sys/mounts/secret",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"sys",
"mounts",
"secret"
]
}
},
"status": "No Content",
"code": 204,
"_postman_previewlanguage": "json",
"header": [
{
"key": "Cache-Control",
"value": "no-store"
},
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Date",
"value": "Thu, 15 Apr 2021 09:03:41 GMT"
}
],
"cookie": [],
"body": null
}
]
},
{
"name": "编辑kv引擎路径和kv键值对",
"request": {
"method": "POST",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\"action1\":\"helloaaaa111\"}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://127.0.0.1:8200/v1/secret/test",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"secret",
"test"
]
}
},
"response": [
{
"name": "新增kv引擎路径和kv键值对",
"originalRequest": {
"method": "POST",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\"action1\":\"helloaaaa111\"}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://127.0.0.1:8200/v1/secret/test",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"secret",
"test"
]
}
},
"status": "No Content",
"code": 204,
"_postman_previewlanguage": "json",
"header": [
{
"key": "Cache-Control",
"value": "no-store"
},
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Date",
"value": "Thu, 15 Apr 2021 09:23:00 GMT"
}
],
"cookie": [],
"body": null
}
]
},
{
"name": "删除kv引擎路径",
"request": {
"method": "DELETE",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"url": {
"raw": "http://127.0.0.1:8200/v1/secret/test",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"secret",
"test"
]
}
},
"response": [
{
"name": "删除kv引擎路径和键值对",
"originalRequest": {
"method": "DELETE",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"url": {
"raw": "http://127.0.0.1:8200/v1/secret/test",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"secret",
"test"
]
}
},
"status": "No Content",
"code": 204,
"_postman_previewlanguage": "json",
"header": [
{
"key": "Cache-Control",
"value": "no-store"
},
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Date",
"value": "Thu, 15 Apr 2021 09:27:28 GMT"
}
],
"cookie": [],
"body": null
}
]
},
{
"name": "查询kv路径list",
"request": {
"method": "GET",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"url": {
"raw": "http://127.0.0.1:8200/v1/secret/?list=true",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"secret",
""
],
"query": [
{
"key": "list",
"value": "true"
}
]
}
},
"response": [
{
"name": "查询kv路径list",
"originalRequest": {
"method": "GET",
"header": [
{
"key": "X-Vault-Token",
"value": "s.M8UXMFH6p5KUS6S5Ta5ruY6X",
"type": "text"
}
],
"url": {
"raw": "http://127.0.0.1:8200/v1/secret/?list=true",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"secret",
""
],
"query": [
{
"key": "list",
"value": "true"
}
]
}
},
"status": "OK",
"code": 200,
"_postman_previewlanguage": "json",
"header": [
{
"key": "Cache-Control",
"value": "no-store"
},
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Date",
"value": "Thu, 15 Apr 2021 09:31:47 GMT"
},
{
"key": "Content-Length",
"value": "175"
}
],
"cookie": [],
"body": "{\n \"request_id\": \"3497d14c-9a06-96e5-f059-5059f50debcb\",\n \"lease_id\": \"\",\n \"renewable\": false,\n \"lease_duration\": 0,\n \"data\": {\n \"keys\": [\n \"test\"\n ]\n },\n \"wrap_info\": null,\n \"warnings\": null,\n \"auth\": null\n}"
}
]
},
{
"name": "查询kv路径下的键值对",
"request": {
"method": "GET",
"header": [],
"url": null
},
"response": [
{
"name": "查询kv路径下的键值对",
"originalRequest": {
"method": "GET",
"header": [
{
"key": "X-Vault-Token",
"value": "s.3luOj8yNzW4nwvMIMY2SIfQK",
"type": "text"
}
],
"url": {
"raw": "http://127.0.0.1:8200/v1/secret/test",
"protocol": "http",
"host": [
"172",
"26",
"239",
"235"
],
"port": "8200",
"path": [
"v1",
"secret",
"test"
]
}
},
"status": "OK",
"code": 200,
"_postman_previewlanguage": "json",
"header": [
{
"key": "Cache-Control",
"value": "no-store"
},
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Date",
"value": "Thu, 15 Apr 2021 09:59:37 GMT"
},
{
"key": "Content-Length",
"value": "190"
}
],
"cookie": [],
"body": "{\n \"request_id\": \"b33aeb76-0381-2edb-2ed0-1a0019f7be75\",\n \"lease_id\": \"\",\n \"renewable\": false,\n \"lease_duration\": 2764800,\n \"data\": {\n \"action1\": \"helloaaaa111\"\n },\n \"wrap_info\": null,\n \"warnings\": null,\n \"auth\": null\n}"
}
]
}
],
"protocolProfileBehavior": {}
}
http请求时表头一定要带着token,第一次请求可以带root_token,用root_token新建其他策略的token后,可以用其他token进行请求。
PKI分发
具体PKI分发可以参考以下两篇:
使用vault pki engine 方便的管理证书
vault 使用 中间ca 进行证书管理
数据库动态密码管理
数据库动态密码管理可参考:
https://www.jianshu.com/p/019a9eb51ae6
最后总结了以下常用的CLI命令(建议去官网文档根据需要自行查看):
常用CLI命令操作
secrets engine:密码引擎
KV Secrets Engine - Version 2:密码引擎的一种,保存普通的键值对
使KV Secrets Engine - Version 2引擎可用
vault secrets enable -version=2 kv
或
vault secrets enable kv-v2
存储键值对
使用vault kv put
命令来存储密码键值对
如:vault kv put secret/hello foo=world
即是往secret/hello这个路径下存储了foo,world这个键值对
存储多个键值对
vault kv put secret/hello foo=world excited=yes
读取键值对
使用vault kv get
命令来读取键值对
如:vault kv get secret/hello
通过key获取value命令:
vault kv get -field=excited secret/hello
得到的是yes值
以json格式显示全部结果:
vault kv get -format=json secret/hello
用jq工具过滤结果:
vault kv get -format=json secret/hello | jq -r .data.data.excited
也能得到yes值
删除键值对
vault kv delete secret/hello
使一个密码引擎可用命令
如:
vault secrets enable -path=kv kv
Success! Enabled the kv secrets engine at: kv/
或
vault secrets enable kv
遍历出所有的密码引擎
$ vault secrets list
Path Type Accessor Description
---- ---- -------- -----------
cubbyhole/ cubbyhole cubbyhole_78189996 per-token private secret storage
identity/ identity identity_ac07951e identity store
kv/ kv kv_15087625 n/a
secret/ kv kv_4b990c45 key/value secret storage
sys/ system system_adff0898 system endpoints used for control, policy and debugging
遍历出某个密码引擎下面所有的路径
如上面的kv引擎
$ vault kv list kv/
Keys
----
hello
结构大概为 密码引擎(Secrets Engine)\ 引擎下面的地址(Secrets Engine Path)\ 保存在地址下面的键值对(key=value)
使一个密码引擎不可用
$ vault secrets disable kv/
Success! Disabled the secrets engine (if it existed) at: kv/
动态密码生成
以取名为aws密码引擎为例:
使aws引擎可用:
vault secrets enable -path=aws aws
或
vault secrets enable aws
导入一个环境变量
export AWS_ACCESS_KEY_ID=
export AWS_SECRET_ACCESS_KEY=
可以用初始化的key
配置aws密码引擎
$ vault write aws/config/root \
access_key=$AWS_ACCESS_KEY_ID \
secret_key=$AWS_SECRET_ACCESS_KEY \
region=us-east-1
Success! Data written to: aws/config/root
新建my-role角色
$ vault write aws/roles/my-role \
credential_type=iam_user \
policy_document=-<
生成动态密码(vault read
$ vault read aws/creds/my-role
Key Value
--- -----
lease_id aws/creds/my-role/0bce0782-32aa-25ec-f61d-c026ff22106e
lease_duration 768h
lease_renewable true
access_key AKIAJELUDIANQGRXCTZQ
secret_key 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
security_token
吊销密码(vault lease
$ vault lease revoke aws/creds/my-role/0bce0782-32aa-25ec-f61d-c026ff22106
Success! Revoked lease: aws/creds/my-role/0bce0782-32aa-25ec-f61d-c026ff22106e
帮助命令
如新可用了一个密码引擎:
vault secrets enable -path=aws aws
引擎帮助(Engine Help)命令:
$ vault path-help aws
### DESCRIPTION
The AWS backend dynamically generates AWS access keys for a set of
IAM policies. The AWS access keys have a configurable lease set and
are automatically revoked at the end of the lease.
After mounting this backend, credentials to generate IAM keys must
be configured with the "root" path and policies must be written using
the "roles/" endpoints before any access keys can be generated.
### PATHS
The following paths are supported by this backend. To view help for
any of the paths below, use the help command with any route matching
the path pattern. Note that depending on the policy of your auth token,
you may or may not be able to access certain paths.
^config/lease$
Configure the default lease information for generated credentials.
^config/root$
Configure the root credentials that are used to manage IAM.
^creds/(?P\w+)$
Generate an access key pair for a specific role.
^roles/(?P\w+)$
Read and write IAM policies that access keys can be made for.
路径帮助(Path Help)命令:
如:
$ vault path-help aws/creds/my-non-existent-role
Request: creds/my-non-existent-role
Matching Route: ^creds/(?P\w(([\w-.]+)?\w)?)$
Generate an access key pair for a specific role.
### PARAMETERS
name (string)
Name of the role
### DESCRIPTION
This path will generate a new, never before used key pair for
accessing AWS. The IAM policy used to back this key pair will be
the "name" parameter. For example, if this backend is mounted at "aws",
then "aws/creds/deploy" would generate access keys for the "deploy" role.
The access keys will have a lease associated with them. The access keys
can be revoked by using the lease ID.
身份验证(Authentication)
默认身份验证是token
新建token
vault默认读取root token从$VAULT_TOKEN环境变量值里,root token 被分配的是root policy,有各种权限,可以新建token来继承root token,也拥有root policy的权限。
$ vault token create
Key Value
--- -----
token s.iyNUhq8Ov4hIAx6snw5mB2nL
token_accessor maMfHsZfwLB6fi18Zenj3qh6
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]
这里新建出来的token即是s.iyNUhq8Ov4hIAx6snw5mB2nL
用这个token也可以登录vault
如:
$ vault login s.iyNUhq8Ov4hIAx6snw5mB2nL
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token s.iyNUhq8Ov4hIAx6snw5mB2nL
token_accessor maMfHsZfwLB6fi18Zenj3qh6
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]
再建一个,每个token都是独一无二的。
$ vault token create
Key Value
--- -----
token s.TsKT5ubouZ7TF26Eg7wNIl3k
token_accessor b1d0curWHYqmgCndk0G1cM6R
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]
吊销token
如:
$ vault token revoke s.iyNUhq8Ov4hIAx6snw5mB2nL
Success! Revoked token (if it existed)
启用新建其他类型的身份验证
比如 github:
$ vault auth enable github
Success! Enabled github auth method at: github/
可用成功,可获取路径在auth/github/
为github身份验证设置organization
$ vault write auth/github/config organization=hashicorp
Success! Data written to: auth/github/config
为engineering团队设置 default,applications policies身份验证
$ vault write auth/github/map/teams/engineering value=default,applications
Success! Data written to: auth/github/map/teams/engineering
遍历所有的身份验证
$ vault auth list
Path Type Description
---- ---- -----------
github/ github n/a
token/ token token based credentials
查看身份验证帮助(Auth Help)信息
$ vault auth help github
Usage: vault login -method=github [CONFIG K=V...]
The GitHub auth method allows users to authenticate using a GitHub
personal access token. Users can generate a personal access token from the
settings page on their GitHub account.
Authenticate using a GitHub token:
$ vault login -method=github token=abcd1234
## ...
尝试登录并查看token信息
$ vault login -method=github
GitHub Personal Access Token (will be hidden):
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token s.DNtKCjVQ1TxAzgMqtDuwjjC2
token_accessor e7zLJuPg2tLpav66ZSu5AyDC
token_duration 768h
token_renewable true
token_policies [default applications]
token_meta_org hashicorp
token_meta_username my-user
吊销所有github下的身份验证token
$ vault token revoke -mode path auth/github
使github身份验证信息不可用
$ vault auth disable github
Success! Disabled the auth method (if it existed) at: github/
政策(Policies)
在hcl文件里声明
如:
# Dev servers have version 2 of KV secrets engine mounted by default, so will
# need these paths to grant permissions:
path "secret/data/*" {
capabilities = ["create", "update"]
}
path "secret/data/foo" {
capabilities = ["read"]
}
这样声明之后,secret/data/路径下除了secret/data/foo之外都可以新建和更改,secret/data/foo只可以读取
默认会有root和default两个政策,root有所有权限
查看政策命令
查看default policy
$ vault policy read default
写入政策
利用vault policy write命令写入政策
帮助命令:
$ vault policy write -h
Usage: vault policy write [options] NAME PATH
Uploads a policy with name NAME from the contents of a local file PATH or
stdin. If PATH is "-", the policy is read from stdin. Otherwise, it is
loaded from the file at the given path on the local disk.
Upload a policy named "my-policy" from "/tmp/policy.hcl" on the local disk:
$ vault policy write my-policy /tmp/policy.hcl
Upload a policy from stdin:
$ cat my-policy.hcl | vault policy write my-policy -
...snip...
写入:
$ vault policy write my-policy - << EOF
# Dev servers have version 2 of KV secrets engine mounted by default, so will
# need these paths to grant permissions:
path "secret/data/*" {
capabilities = ["create", "update"]
}
path "secret/data/foo" {
capabilities = ["read"]
}
EOF
遍历所有政策
$ vault policy list
default
my-policy
root
查看my-policy
$ vault policy read my-policy
# Dev servers have version 2 of KV secrets engine mounted by default, so will
# need these paths to grant permissions:
path "secret/data/*" {
capabilities = ["create", "update"]
}
path "secret/data/foo" {
capabilities = ["read"]
}
测试
新建一个my-policy政策的token
$ vault token create -policy=my-policy
Key Value
--- -----
token s.X6gvFko7chPilgV0lpWXsdeu
token_accessor kwgaMv7lz09a5oULHIT3UQ6z
token_duration 768h
token_renewable true
token_policies ["default" "my-policy"]
identity_policies []
policies ["default" "my-policy"]
往secret/data/creds里写入一个密码
$ VAULT_TOKEN= vault kv put secret/creds password="my-long-password"
Key Value
--- -----
created_time 2018-05-22T18:05:42.537496856Z
deletion_time n/a
destroyed false
version 1
上面的
注:KV v2 密码引擎用vault kv 命令时可以省略/data路径
尝试往secret/data/foo里写入信息
$ VAULT_TOKEN= vault kv put secret/foo robot=beepboop
Error writing data to secret/data/foo: Error making API request.
URL: PUT http://127.0.0.1:8200/v1/secret/data/foo
Code: 403. Errors:
* permission denied
权限被拒绝了,因为这个政策这个路径只有读取权限
将政策跟身份验证方法关联
查看approle/是否被可用
$ vault auth list | grep 'approle/'
如果没有可用则可用
$ vault auth enable approle
可用一个AppRole 'my-role' 关联my-policy
$ vault write auth/approle/role/my-role \
secret_id_ttl=10m \
token_num_uses=10 \
token_ttl=20m \
token_max_ttl=30m \
secret_id_num_uses=40 \
token_policies=my-policy
验证AppRole
$ export ROLE_ID="$(vault read -field=role_id auth/approle/role/my-role/role-id)"
export SECRET_ID="$(vault write -f -field=secret_id auth/approle/role/my-role/secret-id)"
$ vault write auth/approle/login role_id="$ROLE_ID" secret_id="$SECRET_ID"
Key Value
--- -----
token s.Sh9h1wZ9ycATeSaASoOQvovr
token_accessor xCgUIu6WWLM9opkEkAiNLsRc
token_duration 20m
token_renewable true
token_policies ["default" "my-policy"]
identity_policies []
policies ["default" "my-policy"]
token_meta_role_name my-role