Unhardcode tables for chains.
There is a way to manage tables in rules, but there is no way to
manage tables for chains when setting policy.
Looks like pillar structure is bad from the beginning and to
not break backward compatibility, as same chain names may occur in
different tables, so it is proposed to check if 'chain.policy' is
map. And if it is, specific policies would be ensured for specific
tables, otherwise table 'filter' would be used as a fallback.
To ensure chains in specific tables we iterate over all rules in
each chain.
This hash is valid:
parameters:
iptables:
service:
enabled: true
chain:
OUTPUT:
policy: ACCEPT
FORWARD:
policy:
- table: mangle
policy: DROP
INPUT:
policy:
- table: nat
policy: ACCEPT
rules:
- jump: ACCEPT
protocol: icmp
POSTROUTING:
rules:
- jump: MASQUERADE
protocol: icmp
out_interface: ens3
table: nat
Prod-Related: CEEMCP-12
Prod-Related: EME-313
Change-Id: Ib5ba97dad165d3ef2dec7e053b391ea36a996103
diff --git a/README.rst b/README.rst
index c0a25af..c079424 100644
--- a/README.rst
+++ b/README.rst
@@ -132,6 +132,34 @@
source_network: 2001:DB8::/32
jump: ACCEPT
+
+You may set policy for chain in specific table
+If 'table' key is omitted, 'filter' table is assumed
+
+.. code-block:: yaml
+
+ parameters:
+ iptables:
+ service:
+ enabled: true
+ chain:
+ OUTPUT:
+ policy: ACCEPT
+
+Specify policy directly
+
+.. code-block:: yaml
+
+ parameters:
+ iptables:
+ service:
+ enabled: true
+ chain:
+ FORWARD:
+ policy:
+ - table: mangle
+ policy: DROP
+
Read more
=========
diff --git a/iptables/_rule.sls b/iptables/_rule.sls
index 3ae7c22..e967fae 100644
--- a/iptables/_rule.sls
+++ b/iptables/_rule.sls
@@ -1,19 +1,20 @@
-iptables_{{ chain_name }}_{{ rule_name }}:
+{%- set table = rule.get('table', 'filter') %}
+iptables_{{ table }}_{{ chain_name }}_{{ rule_name }}:
{%- if rule.position is defined %}
iptables.insert:
- position: {{ rule.position }}
{%- else %}
iptables.append:
- require:
- {%- if loop.index != 1 %}
- - iptables: iptables_{{ chain_name }}_{% if service_name is defined %}{{ service_name }}_{% endif %}{{ loop.index - 1 }}
- {%- else %}
- {%- for chain in chains %}
- - iptables: iptables_{{ chain }}
- {%- endfor %}
+ {%- if loop.index != 1 %}
+ - iptables: iptables_{{ table }}_{{ chain_name }}_{% if service_name is defined %}{{ service_name }}_{% endif %}{{ loop.index - 1 }}
+ {%- else %}
+ {%- for chain in chains %}
+ - iptables: iptables_{{ table }}_{{ chain }}
+ {%- endfor %}
+ {%- endif %}
{%- endif %}
- {%- endif %}
- - table: {{ rule.get('table', 'filter') }}
+ - table: {{ table }}
- chain: {{ chain_name }}
{%- if rule.family is defined %}
- family: {{ rule.family }}
@@ -38,9 +39,9 @@
{%- endif %}
{%- if rule.destination_ports is defined %}
- dports:
- {%- for port in rule.destination_ports %}
+ {%- for port in rule.destination_ports %}
- {{ port }}
- {% endfor %}
+ {% endfor %}
{%- endif %}
{%- if rule.source_port is defined %}
- sport: {{ rule.source_port }}
@@ -60,27 +61,34 @@
{%- if rule.to_source is defined %}
- to-source: {{ rule.to_source }}
{%- endif %}
- {%- if rule.source_network is defined %}
+ {%- if rule.source_network is defined %}
- source: {{ rule.source_network }}
{%- endif %}
- {%- if rule.destination_network is defined %}
+ {%- if rule.destination_network is defined %}
- destination: {{ rule.destination_network }}
{%- endif %}
- {%- if rule.log_prefix is defined %}
+ {%- if rule.log_prefix is defined %}
- log-prefix: '{{ rule.log_prefix }}'
{%- endif %}
- {%- if rule.log_level is defined %}
+ {%- if rule.log_level is defined %}
- log-level: {{ rule.log_level }}
{%- endif %}
- {%- if rule.limit is defined %}
+ {%- if rule.limit is defined %}
- limit: '{{ rule.limit }}'
{%- endif %}
{%- if chain.policy is defined %}
+ {%- if chain.policy is string %}
- require_in:
- - iptables: iptables_{{ chain_name }}_policy
+ - iptables: iptables_filter_{{ chain_name }}_policy
+ {%- else %}
+ {%- if table in chain.policy %}
+ - require_in:
+ - iptables: iptables_{{ table }}_{{ chain_name }}_policy
+ {%- endif %}
+ {%- endif %}
{%- endif %}
{%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
- require:
- - iptables: iptables_{{ chain_name }}{% if rule.family is defined %}_{{ rule.family }}{% endif %}
+ - iptables: iptables_{{ table}}_{{ chain_name }}{% if rule.family is defined %}_{{ rule.family }}{% endif %}
{%- endif %}
- save: True
diff --git a/iptables/rules.sls b/iptables/rules.sls
index f3fb66f..33c4747 100644
--- a/iptables/rules.sls
+++ b/iptables/rules.sls
@@ -4,48 +4,87 @@
{%- set chains = service.get('chain', {}).keys() %}
{%- for chain_name, chain in service.get('chain', {}).iteritems() %}
-iptables_{{ chain_name }}:
+{%- set tables = [] %}
+{%- for rule in chain.get('rules', []) %}
+{%- set table = rule.get('table', 'filter') %}
+{%- if table not in tables %}
+{%- do tables.append(table) %}
+{%- endif %}
+{%- endfor %}
+{%- if chain.policy is defined %}
+{%- if chain.policy is string %}
+{%- if 'filter' not in tables %}
+{%- do tables.append('filter') %}
+{%- endif %}
+{%- else %}
+{%- for policy in chain.policy %}
+{%- if policy.table not in tables %}
+{%- do tables.append(policy.table) %}
+{%- endif %}
+{%- endfor %}
+{%- endif %}
+{%- endif %}
+
+{%- for table in tables %}
+iptables_{{ table }}_{{ chain_name }}:
iptables.chain_present:
- family: ipv4
- name: {{ chain_name }}
- - table: filter
+ - table: {{ table }}
- require:
- pkg: iptables_packages
{%- if grains.ipv6|default(False) and service.ipv6|default(True) %}
-iptables_{{ chain_name }}_ipv6:
+iptables_{{ table }}_{{ chain_name }}_ipv6:
iptables.chain_present:
- family: ipv6
- name: {{ chain_name }}
- - table: filter
+ - table: {{ table }}
- require:
- pkg: iptables_packages
{%- if chain.policy is defined %}
+{%- if chain.policy is string %}
- require_in:
- - iptables: iptables_{{ chain_name }}_ipv6_policy
+ - iptables: iptables_filter_{{ chain_name }}_ipv6_policy
+{%- else %}
+{%- if table in chain.policy %}
+ - require_in:
+ - iptables: iptables_filter_{{ chain_name }}_ipv6_policy
+{%- endif %}
+{%- endif %}
{%- endif %}
{%- endif %}
+{%- endfor %}
{%- if chain.policy is defined %}
-iptables_{{ chain_name }}_policy:
+
+{%- if chain.policy is string %}
+{%- set map = [{'table':'filter', 'policy':chain.policy}] %}
+{%- else %}
+{%- set map = chain.policy %}
+{%- endif %}
+
+{%- for policy in map %}
+iptables_{{ policy.table }}_{{ chain_name }}_policy:
iptables.set_policy:
- family: ipv4
- chain: {{ chain_name }}
- - policy: {{ chain.policy }}
- - table: filter
+ - policy: {{ policy.policy }}
+ - table: {{ policy.table }}
- require:
- - iptables: iptables_{{ chain_name }}
+ - iptables: iptables_{{ policy.table }}_{{ chain_name }}
-{%- if grains.ipv6|default(False) and service.ipv6|default(True) %}
-iptables_{{ chain_name }}_ipv6_policy:
+{%- if grains.ipv6|default(False) and service.ipv6|default(True) %}
+iptables_{{ policy.table }}_{{ chain_name }}_ipv6_policy:
iptables.set_policy:
- family: ipv6
- chain: {{ chain_name }}
- - policy: {{ chain.policy }}
- - table: filter
+ - policy: {{ policy.policy }}
+ - table: {{ policy.table }}
- require:
- - iptables: iptables_{{ chain_name }}_ipv6
-{%- endif %}
+ - iptables: iptables_{{ policy.table }}_{{ chain_name }}_ipv6
+{%- endif %}
+{%- endfor %}
{%- endif %}
{%- for service_name, service in pillar.items() %}
diff --git a/tests/pillar/iptables_server.sls b/tests/pillar/iptables_server.sls
index b6a1219..408b273 100644
--- a/tests/pillar/iptables_server.sls
+++ b/tests/pillar/iptables_server.sls
@@ -3,6 +3,9 @@
enabled: true
chain:
INPUT:
+ policy:
+ - table: nat
+ policy: ACCEPT
rules:
- position: 1
table: filter
@@ -11,3 +14,15 @@
source_network: 127.0.0.1
jump: ACCEPT
comment: Blah
+ OUTPUT:
+ policy: ACCEPT
+ FORWARD:
+ policy:
+ - table: mangle
+ policy: DROP
+ POSTROUTING:
+ rules:
+ - jump: MASQUERADE
+ protocol: icmp
+ out_interface: ens3
+ table: nat