查找方法解释结果

huangapple go评论73阅读模式
英文:

Lookup method interpreting result

问题

I am using a lookup method which returns a password (using cyberark.. but that is not relevant for this issue description)

当密码中包含花括号并且第二个查找参数中有变量时,结果会被Jinja解释。

Here is a simplified example.

在清单变量中,我有以下值:

existing_var: 'just a string' ansible_password: '{{ lookup("mylookup", "{{ existing_var }}") }}'

其中mylookup是一个测试查找方法,它始终返回一个单个字符串"x{g{%Y}",如下所示。 (这必须存储在ansible配置文件中指定的查找文件夹中,名称为"mylookup.py"。)

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible.errors import AnsibleError
from ansible.plugins.lookup import LookupBase

class LookupModule(LookupBase):
    def run(self, terms, variables=None, **kwargs):
        #we return always the same string without taking account of any parameter.
        return ["x{g{%Y"]

我不希望查找结果被解释。

但实际上是被解释了。

这导致了一个ansible解释错误:"遇到未知标签'Y'.. 字符串:{%Y"。

当查找的第二个参数中没有花括号时,我注意到这种情况不会发生。

ansible_password: '{{ lookup("mylookup", "simple string without curly braces.")}}'

如何避免这种解释?

为了解决这个问题,我尝试增加日志详细程度并启用调试。没有有用的日志,ansible一旦调用查找方法就会失败。我已经将复杂的密码查找方法存根化,以简化问题并在这里展示。我尝试使用过滤器"safe"和"string",但都没有效果。我已经删除了第二个参数,并观察到在这种情况下,返回的字符串不会被解释。

英文:

I am using a lookup method which returns a password (using cyberark.. but that is not relevant for this issue description)

When the password happens to contain a curly brace and there is a variable in second lookup parameter, the result is interpreted by jinja.

Here is a simplified example.

Among the inventory variables I have the following values:

existing_var: 'just a string'
ansible_password: '{{ lookup("mylookup", "{{ existing_var }}") }}' 

Where mylookup is a test lookup method, that returns always a single string "x{g{%Y" such as below.
(this has to be stored in the lookup folder specified in the ansible config files, with name "mylookup.py".)

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible.errors import AnsibleError
from ansible.plugins.lookup import LookupBase

class LookupModule(LookupBase):
    def run(self, terms, variables=None, **kwargs):
        #we return always the same string without taking account of any parameter.
        return ["x{g{%Y"]

I don't expect the lookup result to be interpreted.

But it is.

This lead to an ansible interpretation error : "encountered unknown tag 'Y'.. string: {%Y".

Of course being a password in my real world case, the result is not meant to be interpreted.

I have noticed that this does not occur when there is no curly brace in the lookup second parameter.

ansible_password: '{{ lookup("mylookup", "simple string without curly braces.")}}' 

How to avoid this interpretation?

To solve this issue, I have tried to increase log verbosity, and activated debug. There was no useful log, ansible fails as soon as the lookup method is called.
I have stubbed the complex password lookup method to simplify the issue and present it here.
I have tried to use the filters "safe" and "string", to no avail.
I have removed the second parameter, and observed that in this case, the returned string is not interpreted.

答案1

得分: 1

A: 问题不是由lookup插件引起的。Ansible不会对查找进行模板化。请参阅不安全或原始字符串

> "处理查找插件返回的值时,Ansible使用一种称为不安全的数据类型来阻止模板化。"

为测试创建一个minimal reproducible example (mre)项目

shell> tree .
.
├── ansible.cfg
├── hosts
├── pb.yml
└── plugins
    └── lookup
        └── mylookup.py

2 directories, 4 files

配置自定义查找插件的路径DEFAULT_LOOKUP_PLUGIN_PATH

shell> cat ansible.cfg 
[defaults]
gathering = explicit
collections_path = $HOME/.local/lib/python3.9/site-packages/
inventory = $PWD/hosts
lookup_plugins = $PWD/plugins/lookup
retry_files_enabled = false
stdout_callback = yaml

创建自定义查找插件

shell> cat plugins/lookup/mylookup.py 
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

from ansible.plugins.lookup import LookupBase


class LookupModule(LookupBase):
    def run(self, terms, variables=None, **kwargs):
        return ["x{g{%Y"]

,简单的清单

shell> cat hosts
localhost

,以及一个playbook

shell> cat pb.yml 
- hosts: localhost

  vars:

    test_passwd1: "{{ lookup('mylookup') }}"
    test_passwd2: "{{ lookup('mylookup', 'simple string without curly braces') }}"

    test_passwd3: "{{ lookup('mylookup', existing_var) }}"

  tasks:

    - debug:
        var: test_passwd1
    - debug:
        var: test_passwd2

    - debug:
        var: test_passwd3
      vars:
        existing_var: !unsafe x{g{%Y

    - debug:
        var: test_passwd3
      vars:
        existing_var: x{g{%Y

结果:

  • Ansible不会对查找进行模板化
  test_passwd1: "{{ lookup('mylookup') }}"

给出的结果是

  test_passwd1: x{g{%Y
  • 如果添加了一个字面参数,没有任何区别。自定义查找插件mylookup不需要参数。我们在这里添加它是为了展示额外参数的扩展可能会引起问题
test_passwd2: "{{ lookup('mylookup',
                         'simple string without curly braces') }}"

得到相同的结果

  test_passwd2: x{g{%Y
  • 如果要展开包含特殊字符如*{%的变量,必须标记为**!unsafe***
  existing_var: !unsafe x{g{%Y
  test_passwd3: "{{ lookup('mylookup', existing_var) }}"

可以正常工作

  test_passwd3: x{g{%Y
  • 如果省略***!unsafe***
  existing_var: x{g{%Y
  test_passwd3: "{{ lookup('mylookup', existing_var) }}"

展开失败:

> msg: 'An unhandled exception occurred while templating ''{{ lookup(''mylookup'', existing_var) }}''. Error was a <class ''ansible.errors.AnsibleError''>, original message: template error while templating string: Encountered unknown tag ''Y''.. String: x{g{%Y. Encountered unknown tag ''Y''.'

<hr>

<sup>

注意:测试***!unsafe***。给定以下文件

shell&gt; cat test_passwd.txt
x{g{%Y

下面的play按预期工作,因为Ansible阻止了查找插件输出的模板化

shell&gt; cat pb.yml 
- hosts: localhost

  vars:

    test_passwd: "{{ lookup('file', 'test_passwd.txt') }}"

  tasks:

    - debug:
        var: test_passwd
shell&gt; ansible-playbook pb.yml 

PLAY [localhost] ******************************************************************************

TASK [debug] ************************************************************************************
ok: [localhost] => 
  test_passwd: x{g{%Y

PLAY RECAP **************************************************************************************
localhost: ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  • 当你声明一个变量为***!unsafe***时,也不会出现问题。例如,
    - debug:
        var: test_passwd
      vars:
        test_passwd: !unsafe x{g{%Y

给出

  test_passwd: x{g{%Y
  • 当省略***!unsafe***时,任务将失败
    - debug:
        var: test_passwd
      vars:
        test_passwd: x{g{%Y

失败的消息是

> msg: 'An unhandled exception occurred while templating ''x{g{%Y''''. Error was a <class ''ansible.errors.AnsibleError''>, original message: template error while templating string: Encountered unknown tag ''Y''.. String: x{g{%Y. Encountered unknown tag ''Y''.'

</sup>

英文:

Q: "How to avoid this interpretation?" (of the lookup plugin)

A: The problem is not caused by the lookup plugin. Ansible does not template lookups. See Unsafe or raw strings:

> "When handling values returned by lookup plugins, Ansible uses a data type called unsafe to block templating."

Create a mre project for testing

shell&gt; tree .
.
├── ansible.cfg
├── hosts
├── pb.yml
└── plugins
    └── lookup
        └── mylookup.py

2 directories, 4 files

Configure the path to your custom lookup plugin DEFAULT_LOOKUP_PLUGIN_PATH

shell&gt; cat ansible.cfg 
[defaults]
gathering = explicit
collections_path = $HOME/.local/lib/python3.9/site-packages/
inventory = $PWD/hosts
lookup_plugins = $PWD/plugins/lookup
retry_files_enabled = false
stdout_callback = yaml

Create the custom lookup plugin

shell&gt; cat plugins/lookup/mylookup.py 
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

from ansible.plugins.lookup import LookupBase


class LookupModule(LookupBase):
    def run(self, terms, variables=None, **kwargs):
        return [&quot;x{g{%Y&quot;]

, simple inventory

shell&gt; cat hosts
localhost

, and a playbook

shell&gt; cat pb.yml 
- hosts: localhost

  vars:

    test_passwd1: &quot;{{ lookup(&#39;mylookup&#39;) }}&quot;
    test_passwd2: &quot;{{ lookup(&#39;mylookup&#39;, &#39;simple string without curly braces&#39;) }}&quot;

    test_passwd3: &quot;{{ lookup(&#39;mylookup&#39;, existing_var) }}&quot;

  tasks:

    - debug:
        var: test_passwd1
    - debug:
        var: test_passwd2

    - debug:
        var: test_passwd3
      vars:
        existing_var: !unsafe x{g{%Y

    - debug:
        var: test_passwd3
      vars:
        existing_var: x{g{%Y

Results:

  • Ansible does not template lookups
  test_passwd1: &quot;{{ lookup(&#39;mylookup&#39;) }}&quot;

gives

  test_passwd1: x{g{%Y
  • There is no difference if you ad a literal parameter. The custom lookup plugin mylookup doesn't require a parameter. We add it here to show the expansion of this additional parameter may cause the problem
test_passwd2: &quot;{{ lookup(&#39;mylookup&#39;,
                         &#39;simple string without curly braces&#39;) }}&quot;

gives the same result

  test_passwd2: x{g{%Y
  • You have to mark !unsafe a variable that comprises special characters like { or % if you want to expand it
  existing_var: !unsafe x{g{%Y
  test_passwd3: &quot;{{ lookup(&#39;mylookup&#39;, existing_var) }}&quot;

works fine

  test_passwd3: x{g{%Y
  • If you omit !unsafe
  existing_var: x{g{%Y
  test_passwd3: &quot;{{ lookup(&#39;mylookup&#39;, existing_var) }}&quot;

the expansion fails:

> msg: 'An unhandled exception occurred while templating ''{{ lookup(''mylookup'', existing_var) }}''. Error was a <class ''ansible.errors.AnsibleError''>, original message: An unhandled exception occurred while templating ''x{g{%Y''. Error was a <class ''ansible.errors.AnsibleError''>, original message: template error while templating string: Encountered unknown tag ''Y''.. String: x{g{%Y. Encountered unknown tag ''Y''.'

<hr>

<sup>

Note: Test !unsafe. Given the file

shell&gt; cat test_passwd.txt
x{g{%Y
  • The play below works as expected because Ansible blocks the templating of the lookup plugins' output
shell&gt; cat pb.yml 
- hosts: localhost

  vars:

    test_passwd: &quot;{{ lookup(&#39;file&#39;, &#39;test_passwd.txt&#39;) }}&quot;

  tasks:

    - debug:
        var: test_passwd
shell&gt; ansible-playbook pb.yml 

PLAY [localhost] ******************************************************************************

TASK [debug] **********************************************************************************
ok: [localhost] =&gt; 
  test_passwd: x{g{%Y

PLAY RECAP ************************************************************************************
localhost: ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  • The problem also does not appear when you declare a variable is !unsafe. For example,
    - debug:
        var: test_passwd
      vars:
        test_passwd: !unsafe x{g{%Y

gives

  test_passwd: x{g{%Y
  • The task will fail when you omit !unsafe
    - debug:
        var: test_passwd
      vars:
        test_passwd: x{g{%Y

fails

> msg: 'An unhandled exception occurred while templating ''x{g{%Y''. Error was a <class ''ansible.errors.AnsibleError''>, original message: template error while templating string: Encountered unknown tag ''Y''.. String: x{g{%Y. Encountered unknown tag ''Y''.'

</sup>

答案2

得分: -2

你正在遇到的问题是因为mylookup查找方法返回的密码中包含花括号,Jinja会将其解释为模板标签,导致错误。

为了避免这种解释并确保密码字符串被视为文字,你可以使用Jinja提供的quote过滤器。quote过滤器会转义字符串中的字符,以防止它们被解释为模板标签。

以下是如何修改你的代码以使用quote过滤器的示例:

ansible_password: '{{ lookup("mylookup", existing_var | quote) }}'
英文:

The issue you're experiencing occurs because when the password returned by the mylookup lookup method contains curly braces, Jinja interprets it as a template tag, leading to errors.

To avoid this interpretation and ensure that the password string is treated as a literal, you can use the quote filter provided by Jinja. The quote filter escapes characters in a string to prevent them from being interpreted as template tags.

Here's an example of how you can modify your code to use the quote filter:

ansible_password: &#39;{{ lookup(&quot;mylookup&quot;, existing_var | quote) }}&#39;

huangapple
  • 本文由 发表于 2023年6月9日 12:46:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76437279.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定