Go back to just jinja2
This commit is contained in:
parent
094c4d2274
commit
661320558c
9 changed files with 26 additions and 664 deletions
|
|
@ -132,57 +132,3 @@ def test_cli_folder_single_output_file_when_one_format(tmp_path):
|
|||
assert defaults_path.is_file()
|
||||
assert template_path.is_file()
|
||||
assert "to_json" in template_path.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_cli_erb_outputs_puppet_hiera_and_erb_template(tmp_path):
|
||||
cfg = tmp_path / "app.ini"
|
||||
cfg.write_text("[main]\nport = 8080\n", encoding="utf-8")
|
||||
data_out = tmp_path / "common.yaml"
|
||||
template_out = tmp_path / "app.ini.erb"
|
||||
|
||||
exit_code = cli._main(
|
||||
[
|
||||
str(cfg),
|
||||
"-r",
|
||||
"php",
|
||||
"--template-engine",
|
||||
"erb",
|
||||
"--defaults-output",
|
||||
str(data_out),
|
||||
"--template-output",
|
||||
str(template_out),
|
||||
]
|
||||
)
|
||||
|
||||
assert exit_code == 0
|
||||
assert "php::main_port: '8080'" in data_out.read_text(encoding="utf-8")
|
||||
assert "port = <%= @main_port %>" in template_out.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_cli_erb_can_use_separate_puppet_class_namespace(tmp_path):
|
||||
cfg = tmp_path / "app.ini"
|
||||
cfg.write_text("[main]\nport = 8080\n", encoding="utf-8")
|
||||
data_out = tmp_path / "node.yaml"
|
||||
template_out = tmp_path / "app.ini.erb"
|
||||
|
||||
exit_code = cli._main(
|
||||
[
|
||||
str(cfg),
|
||||
"-r",
|
||||
"php_etc_app_ini",
|
||||
"--template-engine",
|
||||
"erb",
|
||||
"--puppet-class",
|
||||
"php",
|
||||
"--defaults-output",
|
||||
str(data_out),
|
||||
"--template-output",
|
||||
str(template_out),
|
||||
]
|
||||
)
|
||||
|
||||
assert exit_code == 0
|
||||
data = data_out.read_text(encoding="utf-8")
|
||||
template = template_out.read_text(encoding="utf-8")
|
||||
assert "php::php_etc_app_ini_main_port: '8080'" in data
|
||||
assert "port = <%= @php_etc_app_ini_main_port %>" in template
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
JinjaTurtle copies parts of the source config (comments, unrecognised lines,
|
||||
structural keys) verbatim into the generated template. If that text contains
|
||||
Jinja2/ERB delimiters it must be neutralised, otherwise attacker-influenced
|
||||
config content becomes live template code that executes when Salt/Ansible/Puppet
|
||||
later renders the template.
|
||||
config content becomes live template code that executes when Ansible later
|
||||
renders the template.
|
||||
|
||||
These tests render the *generated* template the way a downstream tool would and
|
||||
assert that an injected payload never executes. A tripwire object is exposed
|
||||
|
|
@ -14,7 +14,6 @@ the tripwire sentinel, an injected expression executed and the test fails.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
|
@ -25,8 +24,6 @@ import yaml as pyyaml
|
|||
|
||||
from jinjaturtle.escape import (
|
||||
escape_jinja_literal,
|
||||
escape_erb_literal,
|
||||
escape_literal,
|
||||
)
|
||||
|
||||
TRIP = "__TRIPWIRE_FIRED__"
|
||||
|
|
@ -233,43 +230,3 @@ def test_endraw_whitespace_control_cannot_break_out(endraw):
|
|||
rendered = env.from_string(escaped).render(boom=_Boom())
|
||||
assert TRIP not in rendered
|
||||
assert rendered == payload
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"payload",
|
||||
[
|
||||
"<%= system('id') %>",
|
||||
"<% require 'open3' %>",
|
||||
"text <%= 1+1 %> more",
|
||||
"-%> orphan <%",
|
||||
],
|
||||
)
|
||||
def test_escape_erb_literal_removes_executable_tags(payload):
|
||||
escaped = escape_erb_literal(payload)
|
||||
# No raw executable ERB tag should survive that contains the original code.
|
||||
live = re.findall(r"<%[-=#]?(.*?)-?%>", escaped, re.S)
|
||||
for chunk in live:
|
||||
assert "system" not in chunk
|
||||
assert "require" not in chunk
|
||||
# Numeric/expression payloads must be reduced to literal-string prints.
|
||||
|
||||
|
||||
def test_escape_literal_dispatches_by_engine():
|
||||
"""The public ``escape_literal`` wrapper routes to the right engine."""
|
||||
payload = "{{ 7*7 }}"
|
||||
# Default engine is Jinja2.
|
||||
assert escape_literal(payload) == escape_jinja_literal(payload)
|
||||
assert escape_literal(payload, engine="jinja2") == escape_jinja_literal(payload)
|
||||
# An unknown engine falls back to the safer Jinja2 escaping.
|
||||
assert escape_literal(payload, engine="nonsense") == escape_jinja_literal(payload)
|
||||
# ERB routing.
|
||||
erb_payload = "<%= system('id') %>"
|
||||
assert escape_literal(erb_payload, engine="erb") == escape_erb_literal(erb_payload)
|
||||
|
||||
|
||||
def test_escape_literal_jinja_output_is_inert():
|
||||
"""End-to-end: text routed through escape_literal does not execute."""
|
||||
escaped = escape_literal("{{ boom.run('x') }}")
|
||||
env = jinja2.Environment(undefined=jinja2.ChainableUndefined)
|
||||
rendered = env.from_string(escaped).render(boom=_Boom())
|
||||
assert TRIP not in rendered
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ from jinjaturtle.core import (
|
|||
analyze_loops,
|
||||
flatten_config,
|
||||
generate_ansible_yaml,
|
||||
generate_erb_template,
|
||||
generate_jinja2_template,
|
||||
)
|
||||
from jinjaturtle.handlers.yaml import YamlHandler
|
||||
|
|
@ -205,16 +204,6 @@ def test_yaml_loop_preserves_blank_separator_after_list(tmp_path: Path):
|
|||
rendered = Template(template).render(**defaults)
|
||||
assert rendered_expected in rendered
|
||||
|
||||
erb_template = generate_erb_template(
|
||||
fmt,
|
||||
parsed,
|
||||
"role",
|
||||
original_text=text,
|
||||
loop_candidates=loop_candidates,
|
||||
flat_items=flat_items,
|
||||
)
|
||||
assert erb_expected in erb_template
|
||||
|
||||
|
||||
def test_yaml_loop_preserves_following_top_level_comments(tmp_path: Path):
|
||||
from jinja2 import Environment, Template
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue