Note: The Ansible built in role ansible.builtin.iptables makes this post largely irrelevant.
Many systems and applications require certain access to certain ports and protocols. When installing these systems using Ansible it is necessary to also open up the needed ports so that the systems can function correctly. As there is no iptables module in Ansible the shell command is needed to add the iptables rules.
As an example, here is a task that adds a iptables rule to allow Apache to communicate on port 80.
- name: Apache | add apache iptable rule
command: /sbin/iptables -I INPUT 1 -p tcp --dport http -j ACCEPT -m comment --comment "Apache"
sudo: true
Once this is in place you might need to save and/or restart iptables in order to get the rule to be permanently saved. The following two rules will save the iptables rule and restart the iptables service. Note that these commands are specific to Ubuntu and so might not work on your system setup.
- name: save iptables
command: iptables-save
sudo: true
- name: restart iptables
service: name=ufw state=restarted
sudo: true
This allows Apache to communicate, but the trouble is that when the Ansible task is run a second time a second iptables rule will be added. This can cause problems, especially when Ansible is run over and over again to maintain the configuration of the server. For this reason another step must be added to detect for the existence of the rule before it is added. This is done by using the shell module to print the available iptables rules out and store them into a variable. The Ansible keyword 'register' allows any returned value from the current task to be saved as a variable, in this case the variable registered is called 'iptablesrules'.
- name: Apache | get iptables rules
shell: iptables -L
register: iptablesrules
sudo: true
With this in place we can now run the iptables insertion command only when we cannot find a rule that matches the one that we want to add. The find function is run on the iptablesrules.stdout parameter to find the word "Apache" within the contents. This matches the comment that was used in the iptables rule creation. and Here is the modified task.
- name: Apache | add apache iptable rule
command: /sbin/iptables -I INPUT 1 -p tcp --dport http -j ACCEPT -m comment --comment "Apache"
sudo: true
when: iptablesrules.stdout.find("Apache") == -1
The only problem now is that when checking that an Ansible playbook will execute as expected (by using the --check flag) the added conditional will fail. This is because the iptablesrules variable that is generated is not done in this case and so Ansible will error and complain about a missing variable. The way around this it to force the iptables rules variable registry task to always run, even if we are in check mode. To do this we add the always_run flag to the task.
- name: Apache | get iptables rules
shell: iptables -L
register: iptablesrules
always_run: yes
sudo: true
Here is the entire playbook in full. Note that it is better practice to use create the iptables save and restart tasks as handlers and notify them from the needed tasks. This allows them to be reused when generating iptables rules for other services.
---
- name: Apache | get iptables rules
shell: iptables -L
register: iptablesrules
always_run: yes
sudo: true
- name: Apache | add apache iptable rule
command: /sbin/iptables -I INPUT 1 -p tcp --dport http -j ACCEPT -m comment --comment "Apache"
sudo: true
when: iptablesrules.stdout.find("Apache") == -1
- name: save iptables
command: iptables-save
sudo: true
- name: restart iptables
service: name= ufw state=restarted
sudo: true
Comments
Submitted by Gastón Sánchez on Wed, 04/23/2014 - 20:57
PermalinkSubmitted by adrinux on Thu, 04/24/2014 - 17:14
PermalinkSubmitted by iamc on Wed, 04/30/2014 - 09:42
PermalinkSubmitted by Mike Gleason j… on Tue, 11/10/2015 - 13:50
PermalinkSubmitted by Tom on Wed, 05/04/2016 - 14:43
Permalink-name: Save iptables rules command: /sbin/service iptables save sudo: True
Submitted by Am Elemara on Wed, 09/07/2016 - 11:15
PermalinkAdd new comment