Creación de plantillas de zonas firewalld con ansible: problema con la manipulación xml

Creación de plantillas de zonas firewalld con ansible: problema con la manipulación xml

Con ansible 2.9 en RHEL7.6, estoy intentando configurar zonas de firewalld individuales que también incluyen la configuración de reglas enriquecidas. Todo funciona bien, excepto cuando intento agregar una regla enriquecida a la plantilla. En el siguiente ejemplo, intento agregar una regla enriquecida que permita el tráfico VRRP.

Tarea posible:

    - 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 }}"

La variable firewalld_zonesse define en mi defaults/main.yml de la siguiente manera:

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

Fragmento de mi plantilla 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>

Con esto obtengo:

<?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>

Lo que estoy tratando de conseguir es esto:

<?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>

¿Qué necesito cambiar (plantilla y/o variables) para lograr esto?

¡Gracias! j

Respuesta1

Cambiar la parte de la plantilla.

...
{% 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>

información relacionada