I'm trying to configure a flexible iptables management solution with SaltStack, but I find it harder than I thought it would be.
My main requirement: to be able to have a pillar where I keep a list of IPs, which should be whitelisted for SSH access on all minions. This list of IPs will of course change every now and then: some IPs get added, some IPs are removed. The problem that I'm facing is with the removed IPs - when I remove them from the pillar file, SaltStack doesn't remove the actual whitelisting from the minions.
The only workaround I could find, was to create a new key named "removed-ips" and whenever I want to remove an IP, I would add it there. The second for loop will then remove it. Of course, this is a really nasty workaround, is there a better way of doing it?
/srv/pillar/iptables-default.sls:
iptables-default:
whitelisted-ips:
- '55.55.55.55'
- '66.66.66.66'
- '77.77.77.77'
removed-ips:
- '88.88.88.88'
/srv/salt/iptables-default.sls:
{% for ip in salt['pillar.get']('iptables-default:whitelisted-ips') %}
Whitelist OSF IP {{ip}} for SSH access:
iptables.append:
- table: filter
- family: ipv4
- chain: INPUT
- jump: ACCEPT
- match: state
- connstate: NEW
- source: '{{ ip }}'
- dport: 22
- proto: tcp
- save: True
{% endfor %}
{% for ip in salt['pillar.get']('iptables-default:removed-ips') %}
Remove old IPs that are not needed anymore:
iptables.delete:
- table: filter
- family: ipv4
- chain: INPUT
- jump: ACCEPT
- match: state
- connstate: NEW
- source: {{ ip }}
- dport: 22
- proto: tcp
- save: True
{% endfor %}
Rather than using salt's iptables states, I like to manage /etc/iptables/rules.v4 and v6, like this:
firewall-ipv4:
pkg.installed:
- pkgs:
- iptables
- iptables-persistent
file.managed:
- name: /etc/iptables/rules.v4
- source: salt://firewall/files/rules.jinja
- template: jinja
- context:
slspath: {{ slspath }}
family: ipv4
cmd.wait:
- name: iptables-restore rules.v4
- cwd: /etc/iptables
- order: last
- watch:
- file: firewall-ipv4
{{ similar for v6... }}
Where rules.jinja generates the ruleset from pillar. The benefit of this method is that it does the Right Thing when pillar rules are removed, without requiring a flush (i.e. a change) on every highstate. The downside is that it won't notice and revert manual changes to the firewall from the local machine.
I have a formula using the technique here. Ignore the readme note about compatibility issues, it works fine on current salt. Or did last time I checked.