如何防止 Ansible 剧本中的 Jinja2 替换?
How to prevent Jinja2 substitution in Ansible playbook?
在我的剧本中,使用 include_vars
模块包含一个 JSON 文件。 JSON 文件的内容如下:
{
"Component1": {
"parameter1" : "value1",
"parameter2" : "value2"
},
"Component2": {
"parameter1" : "{{ NET_SEG_VLAN }}",
"parameter2": "value2"
}
}
在剧本中包含 JSON 文件后,我正在使用 uri
模块发送一个 http 请求,如下所示:
- name: Configure Component2 variables using REST API
uri:
url: "http://0.0.0.0:5000/vse/api/v1.0/config/working/Component2/configvars/"
method: POST
return_content: yes
HEADER_x-auth-token: "{{ login_resp.json.token }}"
HEADER_Content-Type: "application/json"
body: "{{ Component2 }}"
body_format: json
可以看出,http 请求的正文与 JSON 数据 Component2
一起发送。但是,Jinja2 尝试替换 JSON 文件中的 {{ NET_SEG_VLAN }}
并抛出 undefined
错误。目的不是使用 Jinja2 替换 JSON 文件中的任何内容,而是按照 http 请求中的原样发送正文。
如何防止 Jinja2 替换 JSON 文件中包含的变量?
您应该能够 escape 使用 {% raw %}
和 {% endraw %}
的变量来告诉 Jinja 不要在该块内模板化任何内容。
即使使用 {{'{{NET_SEG_VLAN}}'}}
告诉 jinja 不要在该块内模板化任何内容,您也应该能够转义变量。
!unsafe
When handling values returned by lookup plugins, Ansible uses a data type called unsafe
to block templating. Marking data as unsafe prevents malicious users from abusing Jinja2 templates to execute arbitrary code on target machines. The Ansible implementation ensures that unsafe values are never templated. It is more comprehensive than escaping Jinja2 with {% raw %} ... {% endraw %}
tags.
You can use the same unsafe
data type in variables you define, to prevent templating errors and information disclosure. You can mark values supplied by vars_prompts as unsafe
. You can also use unsafe in playbooks. The most common use cases include passwords that allow special characters like {
or %
, and JSON arguments that look like templates but should not be templated.
我一直在用,像这样:
# Load JSON content, as a raw string with !unsafe
- tags: ["always"]
set_fact:
dashboard_content: !unsafe "{{ lookup('file', './dash.json') | to_json }}"
# Build dictionnary via template
- tags: ["always"]
set_fact:
cc: "{{ lookup('template', './templates/cm_dashboard.yaml.j2') | from_yaml }}"
## cm_dashboard.yaml.j2 content:
hello: {{ cc_dashboard_content }}
# Now, "cc" is a dict variable, with "hello" field protected!
在我的剧本中,使用 include_vars
模块包含一个 JSON 文件。 JSON 文件的内容如下:
{
"Component1": {
"parameter1" : "value1",
"parameter2" : "value2"
},
"Component2": {
"parameter1" : "{{ NET_SEG_VLAN }}",
"parameter2": "value2"
}
}
在剧本中包含 JSON 文件后,我正在使用 uri
模块发送一个 http 请求,如下所示:
- name: Configure Component2 variables using REST API
uri:
url: "http://0.0.0.0:5000/vse/api/v1.0/config/working/Component2/configvars/"
method: POST
return_content: yes
HEADER_x-auth-token: "{{ login_resp.json.token }}"
HEADER_Content-Type: "application/json"
body: "{{ Component2 }}"
body_format: json
可以看出,http 请求的正文与 JSON 数据 Component2
一起发送。但是,Jinja2 尝试替换 JSON 文件中的 {{ NET_SEG_VLAN }}
并抛出 undefined
错误。目的不是使用 Jinja2 替换 JSON 文件中的任何内容,而是按照 http 请求中的原样发送正文。
如何防止 Jinja2 替换 JSON 文件中包含的变量?
您应该能够 escape 使用 {% raw %}
和 {% endraw %}
的变量来告诉 Jinja 不要在该块内模板化任何内容。
即使使用 {{'{{NET_SEG_VLAN}}'}}
告诉 jinja 不要在该块内模板化任何内容,您也应该能够转义变量。
!unsafe
When handling values returned by lookup plugins, Ansible uses a data type called
unsafe
to block templating. Marking data as unsafe prevents malicious users from abusing Jinja2 templates to execute arbitrary code on target machines. The Ansible implementation ensures that unsafe values are never templated. It is more comprehensive than escaping Jinja2 with{% raw %} ... {% endraw %}
tags.You can use the same
unsafe
data type in variables you define, to prevent templating errors and information disclosure. You can mark values supplied by vars_prompts asunsafe
. You can also use unsafe in playbooks. The most common use cases include passwords that allow special characters like{
or%
, and JSON arguments that look like templates but should not be templated.
我一直在用,像这样:
# Load JSON content, as a raw string with !unsafe
- tags: ["always"]
set_fact:
dashboard_content: !unsafe "{{ lookup('file', './dash.json') | to_json }}"
# Build dictionnary via template
- tags: ["always"]
set_fact:
cc: "{{ lookup('template', './templates/cm_dashboard.yaml.j2') | from_yaml }}"
## cm_dashboard.yaml.j2 content:
hello: {{ cc_dashboard_content }}
# Now, "cc" is a dict variable, with "hello" field protected!