Ansible Vault 现在可以解密多个密码

首先

从Ansible 2.4版本开始,通过Ansible Vault,即使使用不同的密码A和密码B对文件进行了单独的加密,也可以使用一个命令进行解密。这在官方文档的「使用encrypt_string在yaml中创建加密变量」、「Vault Ids和多个Vault密码」以及「提供Vault密码」等部分有详细说明。

请概述

    • 2.4からも従来の–vault-password-fileオプションは使えるが、代わりに–vault-idオプションで置き換えることもできる。

 

    • –vault-idオプションは–vault-password-fileオプション以上の機能を持っているが、とりあえず–vault-password-fileオプションと同様にパスワードが書かれたファイルを指定すれば–vault-password-fileオプションと同じ振る舞いをする。

 

    • 復号の際には–vault-idオプションを複数回使うことができるので、別々のパスワードで暗号化された複数のファイルがある場合でもplaybookの実行等を行うことができる。

 

    2.4においては2.3までと比べて嬉しいことはあまりないが、将来はもっと面白いことができるようになるかもしれない。

2.3的范围内的事情

以前,我们使用–vault-password-file选项来指定包含Ansible Vault加密和解密密码的文件。

如果要创建一个新文件,并使用编辑器来描述加密文件的内容的话,

$ ansible-vault create --vault-password-file (パスワードの書かれたファイル) (暗号化する新しいファイル)

如果要加密现有的非加密文件,可以这样做

$ ansible-vault encrypt --vault-password-file (パスワードの書かれたファイル) (暗号化する既存の未暗号化ファイル)

如果想要从标准输入直接创建加密文件。

$ echo -n '(キー): (値)' | ansible-vault encrypt --vault-password-file (パスワードの書かれたファイル) --output (暗号化する新しいファイル)

如果是那样的话就好了。

如果需要解密或查看时,就需要进行解密处理,如ansible-vault decrypt或view,或者在使用ansible-playbook等进行加密文件时,也可以使用–vault-password-file选项。

另外,如果不使用–vault-password-file选项,在ansible-vault命令中会自动要求输入密码,而在使用ansible-playbook等命令时可以添加–ask-vault-pass选项来在运行时要求输入密码。

可以将vault-password-file选项的值配置为ansible.cfg文件中的[defaults]部分中的vault_password_file,或者将环境变量ANSIBLE_VAULT_PASSWORD_FILE设置为相同的值,都能达到相同的效果。

从2.4开始说

2.4版以后,原先可用的功能仍然可用,同时新增了一个名为–vault-id的选项。

将之前指定的–vault-password-file选项替换为–vault-id选项,结果将保持不变。

为了验证,我们在这里创建两个带有密码的文件,命令为echo -n “password1” > vault_multi_pass1 和 echo -n “password2” > vault_multi_pass2。

从先前提到的标准输入直接创建加密文件的命令。

$ echo -n 'key1: value1a' | ansible-vault encrypt --vault-password-file vault_multi_pass1 --output host_vars/multi_pass_host1.yml

以下的命令可以将 –vault-password-file 替换为 –vault-id 并成功执行。

$ echo -n 'key1: value1a' | ansible-vault encrypt --vault-id vault_multi_pass1 --output host_vars/multi_pass_host1.yml

以下是加密文件host_vars/multi_pass_host1.yml的内容。(从633开始的加密部分,即使打出相同的命令,结果也不一定会得到相同的字符串)

$ANSIBLE_VAULT;1.1;AES256
63333233346130323433646534383862623633383130366566636563666663363762396165366636
3061376431346533663362333665333037383462303637320a343838393230636463383162313334
65653333366439356638376634313464313033636266616638323934303437626164643630373637
6139363863353163370a303062346163643039663332306538356665313231653364323937656162
6661

可以使用ansible-vault view –vault-password-file vault_multi_pass1 host_vars/multi_pass_host1.yml或者ansible-vault view –vault-id vault_multi_pass1 host_vars/multi_pass_host1.yml来查看解密后的这个文件。

现在,使用了–vault-id选项与以前有了三个不同之处。

新功能: 标签

首先,可以通过在值中指定”(标签)@(存储密码的文件路径)”来设置标签,即–vault-id选项。

换句话说,当按照以下方式执行时,加密的文件host_vars/multi_pass_host2.yml将被设置标签label2。

$ echo -n 'key1: value1b' | ansible-vault encrypt --vault-id label2@vault_multi_pass1 --output host_vars/multi_pass_host2.yml

multi_pass_host2.yml的内容如下所示。

$ANSIBLE_VAULT;1.2;AES256;label2
39323837616639616662323335353834396338613538383962306562316661323066626463303030
3332646563343637616430643632653233373139643333310a663765633566643531343730636137
65666330323762366431633839343063636636356261653761363763653436313436623864663439
3066313631643166660a346530336461393566623566303166343362386363356338353336613265
3736

host_vars/multi_pass_host1.yml和没有标签的host_vars/multi_pass_host1.yml之间的区别在于,标头部分的$ANSIBLE_VAULT;后面的部分,如果没有标签,则为1.1,如果有标签,则为1.2。这是Ansible Vault格式的版本号。

此外,可以看到在AES256之后添加了”label2″。 这是一个标签。

当前,标签只在ansible.cfg文件中的[defaults]部分设置了vault_id_match = True,或者在环境变量中设置了ANSIBLE_VAULT_ID_MATCH=True时才具有意义。(默认为False)

如果设定值为 False,则会忽略标签;如果设定为 True,则只会解密与指定标签和文件中写入的密码相匹配的内容。

此外,由于标签本身并未加密,根据我在本地测试的限制,似乎可以使用适当的编辑器进行修改。

新功能:使用多个密码进行解密。

其次,如果要解密,可以多次使用-vault-id选项进行指定。

在此处为了验证,使用以下内容创建库存文件multi_pass_host。

multi_pass_host[1:3]

此外,使用playbook创建名为multi_pass_host_site.yml的文件,并按照以下内容进行设置。

- hosts: all
  gather_facts: no
  tasks:
    - debug:
        var: key1

用第二个文件中写好的密码,创建一个额外的文件host_vars/multi_pass_host3.yml并对其进行加密。

$ echo -n 'key1: value1c' | ansible-vault encrypt --vault-id label3@vault_multi_pass2 --output host_vars/multi_pass_host3.yml

要在ANSIBLE_VAULT_ID_MATCH=False的情况下运行此playbook,只需使用–vault-id选项两次指定,如下所示。

$ ansible-playbook -i multi_pass_host --vault-id vault_multi_pass1 --vault-id vault_multi_pass2 multi_pass_host_site.yml

可以将–vault-id选项或者两者之一替换为–vault-password-file选项来执行。

$ ansible-playbook -i multi_pass_host --vault-password-file vault_multi_pass1 --vault-id vault_multi_pass2 multi_pass_host_site.yml
$ ansible-playbook -i multi_pass_host --vault-password-file vault_multi_pass1 --vault-password-file vault_multi_pass2 multi_pass_host_site.yml

如果 ANSIBLE_VAULT_ID_MATCH=True 的话,现在,

    • host_vars/multi_pass_host1.ymlはラベルなし

 

    • host_vars/multi_pass_host2.ymlはラベルがlabel2

 

    host_vars/multi_pass_host3.ymlはラベルがlabel3

因此,要执行playbook,需要使用–vault-id选项三次,如下所示。

$ ANSIBLE_VAULT_ID_MATCH=True ansible-playbook -i multi_pass_host --vault-id vault_multi_pass1 --vault-id label2@vault_multi_pass1 --vault-id label3@vault_multi_pass2 multi_pass_host_site.yml

此外,未指定标签的情况下,可以使用–vault-password-file选项替代–vault-id选项来执行。

$ ANSIBLE_VAULT_ID_MATCH=True ansible-playbook -i multi_pass_host --vault-password-file vault_multi_pass1 --vault-id label2@vault_multi_pass1 --vault-id label3@vault_multi_pass2 multi_pass_host_site.yml

如果host_vars/multi_pass_host3.yml的标签也是label2的话,为了执行playbook,如果ANSIBLE_VAULT_ID_MATCH=False,则标签将被忽略,因此结果与原来一样;但如果ANSIBLE_VAULT_ID_MATCH=True,则结果如下。

$ ANSIBLE_VAULT_ID_MATCH=True ansible-playbook -i multi_pass_host --vault-id vault_multi_pass1 --vault-id label2@vault_multi_pass1 --vault-id label2@vault_multi_pass2 multi_pass_host_site.yml

换句话说,不是每个标签只能设置一个密码,即使标签相同,也可以用多个密码进行加密。最终解密只会对应与指定–vault-id选项中的标签和密码相匹配的项进行。因此,每个需要解密的标签和密码组合都需要指定–vault-id选项的次数。

要实现类似于使用ask-vault-pass选项的功能

第三个选项是,在解密时使用ansible-vault decrypt、ansible-vault view或ansible-playbook等命令时,可以使用prompt作为–vault-id的代替选项来指定密码文件,并在执行时要求输入密码。换句话说,与–ask-vault-pass选项具有相同的效果。

$ ANSIBLE_VAULT_ID_MATCH=True ansible-playbook -i multi_pass_host --vault-id prompt --vault-id label2@prompt --vault-id label2@prompt multi_pass_host_site.yml

当执行此操作时,会要求输入密码3次,输入正确后即可执行。

Vault password (default):
Vault password (label2):
Vault password (label2):

在設定檔等中指定包含密碼的檔案

有关设置的文档可以在 https://docs.ansible.com/ansible/2.4/config.html 找到。

传统上,ansible.cfg文件中的[defaults]部分的vault_password_file的值,或者环境变量ANSIBLE_VAULT_PASSWORD_FILE的值仍然等同于–vault-password-file选项,也就是说只能指定一个没有标签的密码文件。

此外,还可以设置ansible.cfg配置文件中[defaults]部分的vault_identity_list值,或者设置环境变量ANSIBLE_VAULT_IDENTITY_LIST的值,这些值都相当于–vault-id选项的值。
如果要指定多个值,可以使用逗号进行分隔。例如,可以指定vault_multi_pass1,label2@vault_multi_pass1,label2@vault_multi_pass2。
还可以使用值prompt,在使用时会提示输入密码。

这个能做到,什么让你高兴?

坦白说,如果只看这个,要说有什么让人开心的事情,我并没有特别想到的。

因为当需要某个值时,如果该值被加密,但没有提供解密密码,则当前会输出“ERROR!解密失败(未找到可以解密的密钥)”,并且任务将在此时终止。

换句话说,如果只是修改之前的playbook执行命令的标签,那么就无法解密。

$ ANSIBLE_VAULT_ID_MATCH=True ansible-playbook -i multi_pass_host --vault-id vault_multi_pass1 --vault-id label2@vault_multi_pass1 --vault-id label4@vault_multi_pass2 multi_pass_host_site.yml

执行结果如下所示。

PLAY [all] *******************************************************************************
TASK [debug var=key1] ********************************************************************
ERROR! Decryption failed (no vault secrets would found that could decrypt) on (省略)/host_vars/multi_pass_host3.yml

如果在这里不出现错误而是跳过需要该变量的任务,根据权限的不同,即使使用相同的playbook执行也会有不同的任务被执行,这将具有一定的用处。

由于在2.5版本的路线图中提到:“在某些情况下,不同的用户可能希望以不同的访问级别使用相同的播放功能,能够将解密失败的保险库更改为警告或其他内容可以实现这一点。”因此,我们可以期待这一功能的实现。(但是,即使在路线图中提到,延期也是常有的情况)

我觉得如果除了可以用相同的密钥进行加密之外,还能够使用不同的标签或密码进行加密并得到不同的值,那就会很有趣。

换句话说,如果我们将host_vars/multi_pass_host3.yml的内容清空,然后使用Single Encrypted Variable,在label1中使用vault_multi_pass1对”key1: value1d”进行加密,在label2中使用vault_multi_pass2对”key1: value1e”进行加密,则情况如下:

$ ansible-vault encrypt_string --vault-id label1@vault_multi_pass1 --name key1 value1d > host_vars/multi_pass_host3.yml
$ ansible-vault encrypt_string --vault-id label2@vault_multi_pass2 --name key1 value1e >> host_vars/multi_pass_host3.yml

如果使用vault_multi_pass1进行解密,key1的值应为value1d;如果使用vault_multi_pass2进行解密,key1的值应为value1e。但实际上,只有后一个具有有效的相同键(可以看到警告消息:“line 1, column 1, found a duplicate dict key (key1). Using last defined value only.”)。

作为对此的解决方案,可以将key1和key2使用不同的密码进行加密,然后在playbook中写入`{{ key1 | default(key2) }}`。但是,正如上述所述,如果无法解密key1,则会立即发生错误并终止。

所以,我会等待未来的版本。
当然,即使我现在可以通过两个人分别收到的加密文件来执行操作,这对我来说可能会有一定的帮助,但这种情况可能并不太常见。


但是我对传统的方法只感觉到它可能会被弃用。

就像ansible-vault rekey命令重新设置加密密码一样,除了从经典的–vault-password-file选项外,还添加了一个新的–new-vault-password-file选项,用于指定新的密码文件。

即使在只支持到Ansible 2.3的格式1.1版本中,似乎也可以读取1.2版本的格式。→https://github.com/ansible/ansible/pull/22756

尽管官方文档中写着即使为False也会尝试先匹配id,然后按顺序尝试其他的vault ids。从当前行为来看,这个描述似乎没有意义(因为只要有一个变量无法解密就会报错),但未来可能会有所改变。

bannerAds