Ansible中对Vault加密的YAML字符串使用from_yaml过滤器无法解析的问题
Ansible中对Vault加密的YAML字符串使用from_yaml过滤器无法解析的问题
我完全懂你现在的困惑——明明一模一样的YAML内容,明文状态下用from_yaml能完美解析成结构化数据,一存进Ansible Vault加密后,过滤器就“罢工”了,连嵌套变量都提示未定义。咱们先从现象入手,拆解问题根源,再给你靠谱的解决办法。
问题现象复盘
从你提供的Playbook和输出能看到核心差异:
- 明文的
unenc_yaml是带单引号的YAML字符串,经过from_yaml解析后,unenc变成了正常的嵌套字典,unenc.test.ideas能直接访问列表内容; - 加密后的
enc_yaml解密后,字符串里的引号被转义成了\"(输出里显示yaml: \"expanded\"),经过from_yaml后,enc还是原样的字符串,根本没被解析成YAML结构,自然enc.test.ideas会提示未定义。
问题根源
这是因为Ansible Vault在解密过程中,会对加密字符串中的特殊字符(比如双引号)自动添加转义符,破坏了原YAML字符串的格式。当from_yaml处理这个带转义的字符串时,会把它当成纯文本字符串,而不是可解析的YAML结构,所以无法生成嵌套字典。
解决办法
推荐两种方案,优先选第一种,更稳妥:
方案1:直接加密结构化YAML(推荐)
不要把YAML写成字符串形式存Vault,而是直接把结构化的YAML内容加密成Vault变量。这样Ansible解密后会直接返回结构化数据,完全不需要from_yaml过滤器。
修改后的Playbook示例:
- hosts: all vars: unenc_yaml: "test:\n yaml: 'expanded'\n ideas:\n - I\n - have\n - none\n" unenc: "{{ unenc_yaml | from_yaml }}" # 直接加密结构化YAML,而非YAML字符串 enc: !vault | $ANSIBLE_VAULT;1.1;AES256 30646637333834626465376636646430383963393065303033336165323634333830386638323330 3165383834313635316532343661653330343364633561350a653831343230303962663162396437 61656665303339623230646364316262616433643266343863623665336365303533613038333164 6561666362643664640a343264356366386530303562643862363962306666663366373866326139 61343661636364653433313363323066383133623833613863346532643463306461316637373439 37663263316261373134366263366530326362646562303833336639613163656334626338343033 33393565313431326235303235396461376136636563333237363137663862636137613265383137 37303965623562666566 tasks: - name: unenc debug debug: var: unenc - name: unenc.test.ideas debug debug: var: unenc.test.ideas - name: enc debug debug: var: enc - name: enc.test.ideas debug debug: var: enc.test.ideas
运行后,enc会直接和unenc一样是嵌套字典,enc.test.ideas能正常输出列表内容。
方案2:处理转义后再解析(应急方案)
如果因为某些限制,必须存YAML字符串到Vault,可以先用replace过滤器把转义的双引号去掉,再用from_yaml解析:
vars: enc_yaml: !vault | $ANSIBLE_VAULT;1.1;AES256 30646637333834626465376636646430383963393065303033336165323634333830386638323330 3165383834313635316532343661653330343364633561350a653831343230303962663162396437 61656665303339623230646364316262616433643266343863623665336365303533613038333164 6561666362643664640a343264356366386530303562643862363962306666663366373866326139 61343661636364653433313363323066383133623833613863346532643463306461316637373439 37663263316261373134366263366530326362646562303833336639613163656334626338343033 33393565313431326235303235396461376136636563333237363137663862636137613265383137 37303965623562666566 enc: "{{ enc_yaml | replace('\"', '') | from_yaml }}"
注意:这种方法只适合YAML内容里没有需要保留的转义双引号的场景,否则会破坏原内容,所以优先用方案1。
验证效果
无论用哪种方案,最终运行Playbook时,enc.test.ideas都会和unenc.test.ideas一样,正常输出['I', 'have', 'none'],不会再提示变量未定义。
内容来源于stack exchange
相关产品推荐
相关产品推荐

