机密信息一般来说就是一个string,比如用户口令,API key,RSA私钥等,只不过不同场景下会使用不同的格式,编码,加密等,有时是为了适应协议标准,又或者是为了方便人类阅读,再或者就是作者喜欢某种表现形式。所以储存机密信息的问题跟其格式及目的是没有关系的,但是又不能说单单的存一个机密的string,一般折中的方式就是用一个键值对(key-value pair)来储存数据,键可表示其意义,而值则是真正的内容。
Vault当然也支持这种“平常”的方式,甚至专门有“kv”这个二级subcommand来方便用户使用,但底层使用的是type为key/value的Secret Engine。这里也希望用kv这个简单的engine开始一点点介绍相关的概念,先看一个简单的kv指令:
vault server -dev # 还是先用dev server演示
vault secrets list # 显示所有启动(enabled)了的secret engine
这里应该会看到默认启动的四个engine,其Path为:cubbyhole,identity,secret,sys。Path表示这个engine的路径,即其命名空间的根,也是授权空间的根,Type便是secret engine的类型,Accessor会在之后章节系统的讲,Description是个相当模糊的简述。
每一个engine在启动时都需要一个绑定一个Path,可用”-path”指明,若忽略这个选项,则默认以engine Type的”值+/“为Path。我们这里先只看一下这章的主角,即“secret/”这一行,其Type为kv,这个engine是dev server自动启动的,但在prod版不会。所以可以理解为Vault已经运行了vault secrets enable kv -path=secret
。这里的Path为“secret/",就是在说Vault现在有一个只能存kv类Secret的空间,它的命名以“secret/”开始,从此之后,任何以此开始的path都被当作kv来看待,而且也不能创建别的以“secret/”开始的secret engine。现在来看一下最基本的操作put和get:
vault kv put secret/cpsc/100 course_name='computer intro' # 放一个kv在secret/cpsc/100这个位置
若成功的话则会看到这个kv的metadata(元数据):
然后get出来:
vault kv get secret/cpsc/100 # 读取在sercet/cpsc/100上的kv
那还能做哪些事情呢?不妨看一下kv的帮助文档,或者直接输入:
vault kv # 显示kv支持的subcommand,对于其他Vault指令也适用
那如果我想把kv放到自己喜欢的Path怎么办呢,毕竟不能所有kv都以secret/开头,看着就很危险。这里需要开启一个新的type为kv的engine,并以“-path”指明自己希望的prefix:
vault secrets enable -path=csubc kv # 开创一个新的kv空间以csubc/开头
vault secrets list # 看看有没有出现
这是会发现多了一个“csubc/”的kv。这里再强调一次path必须是独一无二的。然后便可以对这个path进行操作了:
vault kv put csubc/cpsc/100 piazza_code='iamnotapasscode' # 放一个kv在secret/cpsc/100这个位置
vault kv list csubc/cpsc/ # 看看这个prefix下有哪些kv
vault kv get csubc/cpsc/100 # 读取在sercet/cpsc/100上的kv
kv的基本用法相信已经很直白了,下面要补充一些额外的tips,为了方便大家很后面其他类型的secret engine比较。vault kv
是一个方便用户使用的快捷方式,但kv也是一种正正经经的engine,那就意味着它也可以通过更加通用的方式来操控。因为不是每一种engine都有这种快捷方式,所以对他们的操作只能使用通用的方式,我们来看一下上面三行指令如果用通用的方式应该是什么样子:
vault write csubc/cpsc/100 piazza_code='iamnotapasscode' # 放一个kv在secret/cpsc/100这个位置
vault list csubc/cpsc/ # 看看这个prefix下有哪些kv
vault read csubc/cpsc/100 # 读取在sercet/cpsc/100上的kv
这里的read,list,write都是不在乎后面路径对应的是什么类型的engine,Vault会动态的判断engine的type并执行相应的操作,对于kv这种可能只是执行了读取storage中的值这样一个简单的操作。这里再次看出,通过路径这种abstraction可以简单干净的generalize针对不同种类engine的具体处理方式。