Назад | Перейти на главную страницу

Создание шаблонов зон firewalld с помощью ansible - проблема с манипуляциями с xml

С помощью ansible 2.9 на RHEL7.6 я пытаюсь настроить отдельные зоны firewalld, которые также включают настройку богатых правил. Все работает нормально, кроме случаев, когда я пытаюсь добавить в шаблон расширенное правило. В приведенном ниже примере я пытаюсь добавить расширенное правило, разрешающее трафик VRRP.

Ответная задача:

    - name: Configure firewalld zones
      template:
        src: zone_template.xml.j2
        dest: /etc/firewalld/zones/{{ item.name }}.xml
      with_items: "{{ firewalld_zones }}"
      notify: reload firewalld
      loop_control:
        label: "{{ item.name }}"

Переменная firewalld_zones определяется в моих настройках по умолчанию / main.yml следующим образом:

firewalld_zones:
  - name: public
    short: "Public"
    description: "Public Zone"
    port:
      - { port: 300, protocol: tcp }
      - { port: 300, protocol: udp }
    rule:
      - protocol:
          - value: "vrrp"
          - action: accept

Фрагмент моего шаблона zone_template.xml.j2:

<?xml version="1.0" encoding="utf-8"?>
<zone{% if item.target is defined %} target="{{ item.target }}"{% endif %}>
  <short>{{ item.short|default(item.name)|upper  }}</short>
{% if item.description is defined %}
  <description>{{ item.description }}</description>
{% endif %}
{% for tag in item %}
{# Settings which can be used several times #}
{% if tag in ['interface','source','service','port','protocol','icmp-block','forward-port','source-port'] %}
{% for subtag in item[tag] %}
  <{{ tag }}{% for name,value in subtag.items() %} {{ name }}="{{ value }}"{% endfor %}/>
{% endfor %}
{# Settings which can be used once #}
{% elif tag in ['icmp-block-inversion','masquerade'] and item[tag] == True %}
  <{{ tag }}/>
{% endif %}
{% endfor %}
{% for rule in item.rule|default([]) %}
  <rule{% if rule.family is defined %} family="{{ rule.family }}"{% endif %}>
{% for tag in rule %}
{% if tag in ['source','destination','service','port','icmp-block','icmp-type','masquerade','forward-port','protocol'] %}
{% for subtag in rule[tag] %}
{% if subtag in ['action'] %}
    <{% for name,value in subtag.items() %}{{ name }}{% endfor %}/>
{% endif %}
    <{{ tag }}{% for name,value in subtag.items() %} {{ name }}="{{ value }}"{% endfor %}/>
{% endfor %}
{% endif %}
  </rule>
{% endfor %}
{% endfor %}
</zone>

С этим я получаю:

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>PUBLIC</short>
  <description>Public Zone</description>
  <port protocol="tcp" port="300"/>
  <port protocol="udp" port="300"/>
  <rule>
    <protocol value="vrrp"/>
    <protocol action="accept"/>
  </rule>
</zone>

Я пытаюсь получить следующее:

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>PUBLIC</short>
  <description>Public Zone</description>
  <port protocol="tcp" port="300"/>
  <port protocol="udp" port="300"/>
  <rule>
    <protocol value="vrrp"/>
    <accept/>
  </rule>
</zone>

Что мне нужно изменить (шаблон и / или переменные) для этого?

Спасибо! J

Измените часть шаблона

...
{% for subtag in rule[tag] %}
{% for name,value in subtag.items() %}
{% if name in ['action'] %}
    <{{ value }}/>
{% else %}
    <{{ tag }} {{ name }}="{{ value }}"/>
{% endif %}
{% endfor %}
{% endfor %}
{% endif %}
{% endfor %}
  </rule>
{% endfor %}
</zone>