如何使用 ansible-vault 2.3.0 解密字符串

How to decrypt string with ansible-vault 2.3.0

我一直在等待 ansible 2.3,因为它将引入 encrypt_string 功能。

不幸的是,我不确定如何读取加密的字符串。

我试过decrypt_string解密(文件),查看(文件)但没有任何效果。

cat test.yml 
---
test: !vault |
     $ANSIBLE_VAULT;1.1;AES256
     37366638363362303836383335623066343562666662386233306537333232396637346463376430
     3664323265333036663736383837326263376637616466610a383430623562633235616531303861
     66313432303063343230613665323930386138613334303839626131373033656463303736366166
     6635346135636437360a313031376566303238303835353364313434363163343066363932346165
     6136

我遇到的错误是 ERROR! input is not vault encrypted data for test.yml

我如何才能解密该字符串,以便在不需要 运行 播放的情况下知道它的价值?

您是否尝试过将加密字符串设置为变量,然后使用 -debug 获取其解密输出?

在您的剧本中将您的加密字符串定义为变量 test,然后执行:

-debug: msg="My Secret value is {{test | replace('\n', '')}}"

在你的剧本中然后运行剧本:

$ ansible-playbook -i localhost YourPlaybook.yml --vault-password-file path/to/your/secret_key_file

您可以通过管道输入,然后告诉 ansible-vault 输出到 stderr,然后将 stdout 重定向到 /dev/null,因为该工具会打印 Decryption successful

新的 Ansible 版本可能不需要 /dev/stdin/ 部分。

类似于:

echo 'YOUR_SECRET_VALUE' | ansible-vault decrypt /dev/stdin --output=/dev/stderr > /dev/null

这是一个例子:

echo '$ANSIBLE_VAULT;1.1;AES256
30636561663762383436386639353737363431353033326634623639666132623738643764366530
6332363635613832396361333634303135663735356134350a383265333537383739353864663136
30393363653361373738656361613435626237643633383261663138653466393332333036353737
3335396631613239380a616531626235346361333737353831376633633264326566623339663463
6235' | ansible-vault decrypt /dev/stdin --output=/dev/stderr > /dev/null

我希望他们实现一种更简单的方法。

编辑:环境变量作为输入:

要在 bash 上使用多行环境变量具有类似的行为,请使用 printf 而不是 echo

示例(密码:123):

export chiphertext='$ANSIBLE_VAULT;1.1;AES256
65333363656231663530393762613031336662613262326666386233643763636339366235626334
3236636366366131383962323463633861653061346538360a386566363337383133613761313566
31623761656437393862643936373564313565663633636366396231653131386364336534626338
3430343561626237660a333562616537623035396539343634656439356439616439376630396438
3730'

printf "%s\n" $chiphertext | ansible-vault decrypt /dev/stdin --output=/dev/stderr > /dev/null

由于整个 vault 文件不能很好地与 git 历史一起使用,因此在变量文件中使用 vault 字符串是可行的方法,这也使得按名称搜索变量更加清晰。

这是一个简单的示例:

我想把 fredsSecretString: value 放入 vars.yml ,(它的值是 fastfredfedfourfrankfurters 但是嘘,不要让人知道!!)

$ ansible-vault encrypt_string 'fastfredfedfourfrankfurters' -n fredsSecretString >> vars.yml
New Vault password: fred
Confirm New Vault password: fred
$ cat vars.yml
fredsSecretString: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          36643662303931336362356361373334663632343139383832626130636237333134373034326565
          3736626632306265393565653338356138626433333339310a323832663233316666353764373733
          30613239313731653932323536303537623362653464376365383963373366336335656635666637
          3238313530643164320a336337303734303930303163326235623834383337343363326461653162
          33353861663464313866353330376566346636303334353732383564633263373862

要解密值,请将加密的字符串送回 ansible-vault 如下:

    $ echo '$ANSIBLE_VAULT;1.1;AES256
    36643662303931336362356361373334663632343139383832626130636237333134373034326565
    3736626632306265393565653338356138626433333339310a323832663233316666353764373733
    30613239313731653932323536303537623362653464376365383963373366336335656635666637
    3238313530643164320a336337303734303930303163326235623834383337343363326461653162
    33353861663464313866353330376566346636303334353732383564633263373862' |
 ansible-vault decrypt && echo
    Vault password: fred
    Decryption successful
    fastfredfedfourfrankfurters
    $

您也可以使用简单的 ansible 命令来实现相应的 host/group/inventory 组合,例如:

$ ansible my_server -m debug -a 'var=my_secret'
my_server | SUCCESS => {
    "my_secret": "373861663362363036363361663037373661353137303762"
}

尽管使用 ansible 调试消息或使用 ansible cli 显示加密字符串值没有问题,但还有一种解决方案可能更方便自动化需求。您可以利用来自 ansible 的 python 库并在您的代码中使用它们(基本上,所有这些都位于 ansible.parsing.*)

1) 提供保管库密码并生成带有机密的 "vault"。

# Load vault password and prepare secrets for decryption
loader = DataLoader()
secret = vault.get_file_vault_secret(filename=vault_password_file, loader=loader)
secret.load()
vault_secrets = [('default', secret)]
_vault = vault.VaultLib(vault_secrets)

2) 使用 AnsibleLoader 加载 yaml 文件:

with codecs.open(input_file, 'r', encoding='utf-8') as f:
    loaded_yaml = AnsibleLoader(f, vault_secrets=_vault.secrets).get_single_data()

3) 如果您需要加密新字符串并更新字典:

    new_encrypted_value = objects.AnsibleVaultEncryptedUnicode.from_plaintext(source_system_password, _vault, vault_secrets[0][1])
    loaded_yaml[target_env]['credentials'][external_system_name]['password'] = new_encrypted_variable

4) 完成处理后,使用 AnsibleDumper 回写:

with open('new_variables.yml','w') as fd:
    yaml.dump(loaded_yaml, fd, Dumper=AnsibleDumper, encoding=None, default_flow_style=False)

这是对我有用的方法,类似于 Scudelletti 所做的,但传递了金库通行证,即

echo '$ANSIBLE_VAULT;1.1;AES256
31363861346536343331393539323936346464386534346337306565626466393764666366363637
6533373165656431393662653463646430663933363431380a336130363131373238326330393931
39343533396161323834613030383339653633393133393932613562396630303530393030396335
3630656237663038630a363032373633363161633464653431386237333262343231313830363965
31393930343532323133386536376637373463396534623631633234393565373337613530643031
38393862616635326339373731353465303364303365336132613566396666626536636533303839
393465653830393231636638643735313666' | ansible-vault decrypt --vault-password-file /path/to/your/.vault_pass.txt /dev/stdin --output=/dev/stderr > /dev/null && echo

由于尾随 && echo,为方便起见,输出将单独占一行。如果你运行遇到任何权限错误,我的金库通行证的权限是644。

希望对您有所帮助!

这一命令仅提取加密数据并将其传递给解密。我更喜欢它,因为您不需要手动提取数据。

$ grep -v vault test.yml | awk '{=;print}' | ansible-vault decrypt

yq 提取加密的 var 值,然后将创建一个临时文件并与 ansible-vault:

一起使用
cat ansible_file.yml | yq -r ".variable_name" > tmp_file.txt

# you can also use 'ansible-vault decrypt'
ansible-vault view --ask-vault-pass tmp_file.txt

这是另一种解密字符串的方法

$ ansible localhost \
       -m debug \
       -a "var=mysecret" \
       -e "@inventory/group_vars/master"
localhost | SUCCESS => {
"mysecret": "somesecret\n"
}

这里的技巧是我们正在传递一个带有 Ansible 拱顶秘密的文件,mysecret 也在其中 ansible 并且它能够解密它。

注意:如果您没有密码来解密 Ansible 保管的加密秘密,您也可以传递它:

$ ansible localhost --vault-password-file=~/.vault_pass.txt \
       -m debug \
       -a "var=mysecret" \
       -e "@inventory/group_vars/master"
localhost | SUCCESS => {
"mysecret": "somesecret\n"
}

这就是我加密和解密内联字符串的方式,此外还用作环境变量。

yq 在这里对于解释 yaml 输入特别有用。

在一行中,如果我要测试加密和解密字符串,我会这样做-

echo -n "test some input that will be encrypted and decrypted" | ansible-vault encrypt_string --vault-id $vault_key --stdin-name testvar_name | yq r - "testvar_name" | ansible-vault decrypt --vault-id $vault_key

我猜通常对此感兴趣的人对解密环境变量感兴趣。这就是我实现该用例的方式,其中 testvar 是加密的环境变量,$vault-id 是您用于 encrypt/decrypt.

的密钥的路径
testvar=$(echo -n "test some input that will be encrypted and stored as an env var" | ansible-vault encrypt_string --vault-id $vault_key --stdin-name testvar_name | base64 -w 0)
result=$(echo $testvar | base64 -d | /var/lib/snapd/snap/bin/yq r - "testvar_name" | ansible-vault decrypt --vault-id $vault_key); echo $result

对于类似 test.yml 的文件:

---
test: !vault |
     $ANSIBLE_VAULT;1.1;AES256
     37366638363362303836383335623066343562666662386233306537333232396637346463376430
     3664323265333036663736383837326263376637616466610a383430623562633235616531303861
     66313432303063343230613665323930386138613334303839626131373033656463303736366166
     6635346135636437360a313031376566303238303835353364313434363163343066363932346165
     6136

以下粗略的实现(显然只推荐用于一些快速的手动操作):

for row in $(cat test.yml | yq -c '.[]'); do
    decrypt() {
     printf "decrypting '%s'" $row | sed -e 's/^"//' -e 's/"$//'
     echo "---"
     printf $row | sed -e 's/^"//' -e 's/"$//' | ansible-vault decrypt -
    }
   echo -e "==\n: $(decrypt '.')"
done

应该可以,前提是您拥有加密数据的密钥

遇到这个问题和这里的答案,我只想添加一个我一起编写的快速 bash 脚本,它会读取整个 yaml 文件,寻找可以解密并转储到屏幕的字符串。

它远非完美,我在 bash 中也不是最热门的,但是,希望这能帮助那些和我处于同样情况的人想要做一个一般的转储。

要使用以下脚本,必须在名为 vault_pass 的文件(当前工作路径)中安装您的保管库密码,并安装 yq and jq。要解析的文件应该是第一个参数。例如./vault_reader.sh group_vars/production.yml

#!/bin/bash
KEY_OR_VALUE=key
for row in $(yq read -j  | jq); do  
    if [ "$KEY_OR_VALUE" == "key" ]
    then
        KEY_OR_VALUE="value"
        echo $(sed -e "s/\"//g" -e "s/\://g" <<<$row)
    else
        KEY_OR_VALUE="key"
        ENC_VALUE=$(sed -e "s/\"//g" -e "s/\://g" -e"s/\,//g"<<<$row)
        if [[ $ENC_VALUE = '$ANSIBLE_VAULT'* ]]; then
            echo -e "$ENC_VALUE" | ansible-vault decrypt --vault-password-file vault_pass
        fi
        echo ""
    fi
done

对于那些想要定义别名而忘记管道和临时文件的人,这里有一个您可以采用的解决方案:

function decrypt_ansible_vault_string() { 
   export FN=
   export KEY=
   ansible-vault view <(yq r $FN $KEY)
   }

用法示例:

$ head myrole/var/main.yml
# Variables here override defaults
website:
  server: 127.0.0.1
  port: 8081
  session:
    hash_key: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          33626439623630633332343836316334376637323738323061373334373733326566613262373036
          6632623432373263613139646432333331313731326232390a653031366564313235323065303865
          32383563393261326633306663663437386134666230373332646234656464356331646335636564

$ decrypt_ansible_vault_string myrole/vars/main.yml website.session.hash_key

这个答案扩展了 注意,我使用的是 this yq,但是任何 yaml 查询工具都可以。此处重要的是使用 subshel​​l 重定向的原则(无临时文件)。 另请注意,您可以添加 --ask-vault-password。然而,使用使用 GPG 加密的秘密要好得多,因为你不必每次都输入密码,而且这种工作流程对于团队(YMVV 和 IHMO)来说要好得多。这里是 a good tutorial on how to use GPG with ansible-vault.

把这个贴在你的 .bashrc 上尽情享受吧。

更新

我对 ansible-vault encrypt\decrypt 工作流程感到沮丧。因此,我创建了一个包装器,用于解密 var 文件中的字符串。检查一下:https://github.com/oz123/ansible-vault-string-helper

一条线就可以做到

ansible localhost -m debug -a var='NAME_OF_ENCRYPTED_VAR' -e "@PATH_TO_FILE_WITH_VARIABLE" --vault-id yourid@/path/to/file

或从命令行输入密码

ansible localhost -m debug -a var='NAME_OF_ENCRYPTED_VAR' -e "@PATH_TO_FILE_WITH_VARIABLE" --ask-vault-pass

您可以将加密后的字符串复制到文件中,但您只需要复制加密部分,而不需要复制其他 yml 部分。

因此您的文件需要更改自:

test: !vault |
     $ANSIBLE_VAULT;1.1;AES256
     37366638363362303836383335623066343562666662386233306537333232396637346463376430
     3664323265333036663736383837326263376637616466610a383430623562633235616531303861
     66313432303063343230613665323930386138613334303839626131373033656463303736366166
     6635346135636437360a313031376566303238303835353364313434363163343066363932346165
     6136

至:

$ANSIBLE_VAULT;1.1;AES256
37366638363362303836383335623066343562666662386233306537333232396637346463376430
3664323265333036663736383837326263376637616466610a383430623562633235616531303861
66313432303063343230613665323930386138613334303839626131373033656463303736366166
6635346135636437360a313031376566303238303835353364313434363163343066363932346136

您将能够使用

进行描述或查看

ansible-vault decrypt --vault-password-file <path to passwordfile> test.yml

ansible-vault view --vault-password-file <path to passwordfile> test.yml

也许删除 .yml 因为那不再有意义了。

我知道这已经有一段时间了,但是当我通过 ansible-vault decrypt 直接通过管道传输时它对我有用,就像这样:

$ echo '$ANSIBLE_VAULT;1.1;AES256
38613538323065373061616466616334306237336461333935393261646131616232643238626635
3336633631366539383039343437306664336165326565650a353233303431613362653838643135
34363763366134393366356339343039313035366164636133326639376334313335316565373330
3435633463313334310a653239313039323135363865313933626464663363656164343662303763
34616663626530656630633839346531653862633332396365396432366234333861' | ansible-vault decrypt
Decryption successful
super-secret-string$ 

以防万一有人感兴趣。我有 ansible 版本 2.9.26

疯狂但优雅的 shell 脚本输出带有解密内联变量的干净 yaml 文件(假设您有 ANSIBLE_VAULT_PASSWORD_FILE set and yq v4 installed):

VARS_FILE=path/to/your/vars_file_with_encrypted_vars.yml
yq -P e "$(for v in $(grep '\!vault' $VARS_FILE | cut -d: -f1); do val=$(yq e .${v} $VARS_FILE | tr -d ' ' | ansible-vault decrypt); echo .$v = \"$val\" \|; done) null = null" $VARS_FILE

有了这个,你可以解密一个只包含一个 ansible 保险库字符串的文件:

cat encrypted_vault_string | ansible-vault decrypt

输出:

Vault passsword: <enter password, is not echoed to you>
Decryption successful
< decrypted string here>

ansible 保险库字符串如下所示:

$ANSIBE_VAULT;1.1;AES256
123456789...
123456789...
123456789...
1234

这也适用于没有中间文件

echo -e '$ANSIBLE_VAULT;1.1;AES256\n123456789...789' | ansible-vault decrypt

尝试解密 /dev/stdin,如 ansible-vault decrypt /dev/stdin 或使用 --vault-password-file=/dev/stdin,就像其他评论者提到的那样,对我来说也失败了,出现 ERROR! [Errno 2] No such file or directory: '/proc/100/fd/pipe:[12930445]'.

然而,--vault-password-file 也需要一个可执行文件来在标准输出上生成密码,因此您实际上可以使用 /bin/cat 来输入密码:

echo password | ansible-vault decrypt --output - --vault-password-file=/bin/cat ./encrypted_vault_file