Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] smtp_tls_policy_maps configuration can only be used either as managed xor unmanaged mapping but not both #132

Open
MEschenbacher opened this issue Jan 4, 2025 · 0 comments
Labels

Comments

@MEschenbacher
Copy link

MEschenbacher commented Jan 4, 2025

Your setup

Formula commit hash / release tag

Versions reports (master & minion)

3007

Pillar / config used

postfix:

  config
    # please note, the list syntax also causes problems with managed mappings
    smtp_tls_policy_maps: 
      - hash:/etc/postfix/tls_policy
      # please note that using socketmap:... causes issues with multiple colons (unpack error during split)
      - socketmap:inet:[::1]:8461:postfix

  mapping:
    smtp_tls_policy_maps:
      - example.org: secure

Bug details

Describe the bug

I'm using the above pillar to use the smtp_tls_policy_maps both as managed mapping i.e. the formula managing /etc/postfix/tls_policy and a custom socketmap (mta sts resolver postfix). This pillar causes jinja rendering errors because as soon as a postfix configuration option is used in combination with the mapping, it is automatically used as string. Also, using the socketmap:... with multiple colons causes rendering errors

Steps to reproduce the bug

error when using a list as configuration option which is a managed mapping:

local:
----------
          ID: postfix-config-file-managed-main.cf
    Function: file.managed
        Name: /etc/postfix/main.cf
      Result: False
     Comment: An exception occurred in this state: Traceback (most recent call last):
                File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/utils/templates.py", line 469, in render_jinja_tmpl
                  output = template.render(**decoded_context)
                File "/opt/saltstack/salt/lib/python3.10/site-packages/jinja2/environment.py", line 1304, in render
                  self.environment.handle_exception()
                File "/opt/saltstack/salt/lib/python3.10/site-packages/jinja2/environment.py", line 939, in handle_exception
                  raise rewrite_traceback_stack(source=source)
                File "<template>", line 123, in top-level template code
                File "/opt/saltstack/salt/lib/python3.10/site-packages/jinja2/sandbox.py", line 392, in call
                  if not __self.is_safe_callable(__obj):
                File "/opt/saltstack/salt/lib/python3.10/site-packages/jinja2/sandbox.py", line 276, in is_safe_callable
                  getattr(obj, "unsafe_callable", False) or getattr(obj, "alters_data", False)
              jinja2.exceptions.UndefinedError: 'list object' has no attribute 'startswith'
              
              During handling of the above exception, another exception occurred:
              
              Traceback (most recent call last):
                File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/state.py", line 2428, in call
                  ret = self.states[cdata["full"]](
                File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/lazy.py", line 160, in __call__
                  ret = self.loader.run(run_func, *args, **kwargs)
                File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/lazy.py", line 1269, in run
                  return self._last_context.run(self._run_as, _func_or_method, *args, **kwargs)
                File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/lazy.py", line 1284, in _run_as
                  return _func_or_method(*args, **kwargs)
                File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/lazy.py", line 1317, in wrapper
                  return f(*args, **kwargs)
                File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/states/file.py", line 3336, in managed
                  ret["changes"] = __salt__["file.check_managed_changes"](
                File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/lazy.py", line 160, in __call__
                  ret = self.loader.run(run_func, *args, **kwargs)
                File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/lazy.py", line 1269, in run
                  return self._last_context.run(self._run_as, _func_or_method, *args, **kwargs)
                File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/lazy.py", line 1284, in _run_as
                  return _func_or_method(*args, **kwargs)
                File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/file.py", line 5700, in check_managed_changes
                  sfn, source_sum, comments = get_managed(
                File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/file.py", line 4938, in get_managed
                  data = salt.utils.templates.TEMPLATE_REGISTRY[template](
                File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/utils/templates.py", line 210, in render_tmpl
                  output = render_str(tmplstr, context, tmplpath)
                File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/utils/templates.py", line 475, in render_jinja_tmpl
                  raise SaltRenderError(f"Jinja variable {exc}{out}", line, tmplstr)
              salt.exceptions.SaltRenderError: Jinja variable 'list object' has no attribute 'startswith'; line 123
              
              ---
              [...]
              {{ set_parameter('smtpd_recipient_restrictions', recipient_restrictions) }}
              
              {# From init.sls #}
              {%- for mapping, data in salt['pillar.get']('postfix:mapping', {}).items() %}
                {%- set file_path = salt['pillar.get']('postfix:config:' ~ mapping) %}
                {%- if file_path.startswith('proxy:') %}    <======================
                  {#- Discard the proxy:-prefix #}
                  {%- set _, file_type, file_path = file_path.split(':') %}
                {%- elif ':' in file_path %}
                  {%- set file_type, file_path = file_path.split(':', 1) %}
                {%- else %}
              [...]

socketmap:... error:

[ERROR   ] Rendering exception occurred
Traceback (most recent call last):
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/utils/templates.py", line 469, in render_jinja_tmpl
    output = template.render(**decoded_context)
  File "/opt/saltstack/salt/lib/python3.10/site-packages/jinja2/environment.py", line 1304, in render
    self.environment.handle_exception()
  File "/opt/saltstack/salt/lib/python3.10/site-packages/jinja2/environment.py", line 939, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 127, in top-level template code
ValueError: too many values to unpack (expected 2)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/utils/templates.py", line 210, in render_tmpl
    output = render_str(tmplstr, context, tmplpath)
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/utils/templates.py", line 513, in render_jinja_tmpl
    raise SaltRenderError(
salt.exceptions.SaltRenderError: Jinja error: too many values to unpack (expected 2)
Traceback (most recent call last):
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/utils/templates.py", line 469, in render_jinja_tmpl
    output = template.render(**decoded_context)
  File "/opt/saltstack/salt/lib/python3.10/site-packages/jinja2/environment.py", line 1304, in render
    self.environment.handle_exception()
  File "/opt/saltstack/salt/lib/python3.10/site-packages/jinja2/environment.py", line 939, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 127, in top-level template code
ValueError: too many values to unpack (expected 2)

; line 127

---
[...]
  {%- set file_path = salt['pillar.get']('postfix:config:' ~ mapping) %}
  {%- if file_path.startswith('proxy:') %}
    {#- Discard the proxy:-prefix #}
    {%- set _, file_type, file_path = file_path.split(':') %}
  {%- elif ':' in file_path %}
    {%- set file_type, file_path = file_path.split(':') %}    <======================
  {%- else %}
    {%- set file_type = postfix.default_database_type %}
  {%- endif %}
  {%- if not file_path.startswith('/') %}
    {%- set file_path = postfix.config_path ~ '/' ~ file_path %}
[...]
---
[ERROR   ] An exception occurred in this state: Traceback (most recent call last):
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/utils/templates.py", line 469, in render_jinja_tmpl
    output = template.render(**decoded_context)
  File "/opt/saltstack/salt/lib/python3.10/site-packages/jinja2/environment.py", line 1304, in render
    self.environment.handle_exception()
  File "/opt/saltstack/salt/lib/python3.10/site-packages/jinja2/environment.py", line 939, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 127, in top-level template code
ValueError: too many values to unpack (expected 2)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/state.py", line 2428, in call
    ret = self.states[cdata["full"]](
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/lazy.py", line 160, in __call__
    ret = self.loader.run(run_func, *args, **kwargs)
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/lazy.py", line 1269, in run
    return self._last_context.run(self._run_as, _func_or_method, *args, **kwargs)
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/lazy.py", line 1284, in _run_as
    return _func_or_method(*args, **kwargs)
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/lazy.py", line 1317, in wrapper
    return f(*args, **kwargs)
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/states/file.py", line 3336, in managed
    ret["changes"] = __salt__["file.check_managed_changes"](
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/lazy.py", line 160, in __call__
    ret = self.loader.run(run_func, *args, **kwargs)
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/lazy.py", line 1269, in run
    return self._last_context.run(self._run_as, _func_or_method, *args, **kwargs)
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/lazy.py", line 1284, in _run_as
    return _func_or_method(*args, **kwargs)
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/file.py", line 5700, in check_managed_changes
    sfn, source_sum, comments = get_managed(
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/file.py", line 4938, in get_managed
    data = salt.utils.templates.TEMPLATE_REGISTRY[template](
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/utils/templates.py", line 210, in render_tmpl
    output = render_str(tmplstr, context, tmplpath)
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/utils/templates.py", line 513, in render_jinja_tmpl
    raise SaltRenderError(
salt.exceptions.SaltRenderError: Jinja error: too many values to unpack (expected 2)
Traceback (most recent call last):
  File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/utils/templates.py", line 469, in render_jinja_tmpl
    output = template.render(**decoded_context)
  File "/opt/saltstack/salt/lib/python3.10/site-packages/jinja2/environment.py", line 1304, in render
    self.environment.handle_exception()
  File "/opt/saltstack/salt/lib/python3.10/site-packages/jinja2/environment.py", line 939, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 127, in top-level template code
ValueError: too many values to unpack (expected 2)

; line 127

---
[...]
  {%- set file_path = salt['pillar.get']('postfix:config:' ~ mapping) %}
  {%- if file_path.startswith('proxy:') %}
    {#- Discard the proxy:-prefix #}
    {%- set _, file_type, file_path = file_path.split(':') %}
  {%- elif ':' in file_path %}
    {%- set file_type, file_path = file_path.split(':') %}    <======================
  {%- else %}
    {%- set file_type = postfix.default_database_type %}
  {%- endif %}
  {%- if not file_path.startswith('/') %}
    {%- set file_path = postfix.config_path ~ '/' ~ file_path %}
[...]

Expected behaviour

I'd like to use the option as described in the pillar.

Attempts to fix the bug

I've tried using maxsplit for the split() call and looping through the configuration variable, however since the configuration template assumes all mapping are already taken care of ({%- set processed_parameters = salt['pillar.get']('postfix:mapping', {}).keys() | list %}), manually specifying the option does also not work as soon as the mapping is defined.

Currently evaluating not using the mapping but a inline table inline:{ {example.org=secure} }.

Additional context

I'm currently still working on it and will refine the bug report.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant