Firewall Module?

Do the Ansible developers have plans to build a firewall module? I think one is strongly needed. Right now we have to use a variety of kludges to get it this to work. Firewall management is an essential sys admin task and should be supported.

Ansible Galaxy needs it because currently there is no standard way for a server role to open the right ports. This means that they have to either make up their own way or ignore it. Both of these are bad. The other CM tools provide provide this capability so it is a standard feature.

I think it should be a module because it spans roles. It also has a global nature in that the handler should only run after all other roles have finished. This is why it doesn’t fit any of Ansible’s current patterns. The module should support iptables and, at least, Red Hat and SUSE (the two commercial distros).

There’s already a module for firewalld.

Some folks, like the Fedora setup playbooks, use lokkit in their plays.

For complex installs, I still highly recommend writing a template for your iptables file (etc) and basing that on the group membership of your hosts, which is easy to do and appropriate.

Drilling holes in your firewall doesn’t really account for the “chained” nature of firewall rules and is a bit basic, and not always appropriate, nor does it model all they can do.

Further, making the explicit choice about what you are letting through is important – rather than letting some roles you downloaded from the internet decide.

Yes, it takes an extra minute or two here or there – but I think constructing your firewall rules via template is still worthwhile, and will make sure you are using the features you need to be using.

Then it’s just a “notify: restart iptables” away, and so forth.

For iptables at least, ferm works very well with a specific set of conf.d directories where other roles can drop their iptables rules and notify ferm role to reload them. It isn’t the same as full module, but the number of tasks would be very similar (instead of potential iptables: module you only call template: module with specified template).

There’s already a module for firewalld.

Some folks, like the Fedora setup playbooks, use lokkit in their plays.

I’m talking about production systems not Fedora.

For complex installs, I still highly recommend writing a template for your iptables file (etc) and basing that on the group membership of your hosts, which is easy to do and appropriate.

Drilling holes in your firewall doesn’t really account for the “chained” nature of firewall rules and is a bit basic, and not always appropriate, nor does it model all they can do.

I don’t know what kind of template you are referring to. iptables does not have a conf file. It has its own persistence format but that is not the same thing.

Further, making the explicit choice about what you are letting through is important – rather than letting some roles you downloaded from the internet decide.

I didn’t reference “some roles you download from the Internet” I referenced Ansible Galaxy. A proper role will provide sensible defaults (like UDP 67,68 for DHCP) and allow the ports to be configured through local variables. That is how all good roles should work.

Yes, it takes an extra minute or two here or there – but I think constructing your firewall rules via template is still worthwhile, and will make sure you are using the features you need to be using.

Then it’s just a “notify: restart iptables” away, and so forth.

It isn’t that simple nor does Ansible handle this case. The rule chains are additive across roles and order is important.
The basic process is:

  • Base role: Setup firewall and insert base rules
  • Role1 : add rules
  • Role 2: add rules
  • Playbook is done. Add closing rules. Restart and save iptables. This spans inventory groups in addition to roles.

Maybe there is another way to do it. That’s fine. The point is that the roles be able to add their own custom rules without having to understand what other roles are doing. This is a common Unix idiom where there is a “conf.d” directory and applications place custom file snippets in it. If order is important then they are often named 01file, 02file, etc. This is the pattern I am arguing for implementing as an Ansible module.

There's already a module for firewalld.

Some folks, like the Fedora setup playbooks, use lokkit in their plays.

I'm talking about production systems not Fedora.

You'd maybe be surprised but Fedora is used in production in some cases.

It's used in some chip design clusters, super computing, and other places.

For complex installs, I still highly recommend writing a template for
your iptables file (etc) and basing that on the group membership of your
hosts, which is easy to do and appropriate.

Drilling holes in your firewall doesn't really account for the "chained"
nature of firewall rules and is a bit basic, and not always appropriate,
nor does it model all they can do.

I don't know what kind of template you are referring to. iptables does not
have a conf file. It has its own persistence format but that is not the
same thing.

Incorrect.

What you produce with /sbin/iptables save can be in fact templated, and
will be used when the service is restarted.

It is in fact configuration.

Further, making the explicit choice about what you are letting through is
important -- rather than letting some roles you downloaded from the
internet decide.

I didn't reference "some roles you download from the Internet" I
referenced Ansible Galaxy. A proper role will provide sensible defaults
(like UDP 67,68 for DHCP) and allow the ports to be configured through
local variables. That is how all good roles should work.

Ansible galaxy is a public site where anyone with a role on github can add
it to the system, so it's basically the internet. Content there is not
blessed or official in any way.

The role can't really declare the ports it needs so easily either -- as
those might be parameterized. And in many cases iptables configuration
is more complicated than generically opening up a port on all interfaces.
This is where basic management of a firewall starts to break down.

There are many that would be scared if roles in Galaxy started poking holes
in my firewall, which is why we don't do it by default.

Plus, the aforementioned groups that want to maintain their own firewall
configurations, which we suggest, and you can see an example of here:

https://github.com/ansible/ansible-examples/blob/master/lamp_haproxy/roles/common/templates/iptables.j2

Yes, it takes an extra minute or two here or there -- but I think

constructing your firewall rules via template is still worthwhile, and will
make sure you are using the features you need to be using.

Then it's just a "notify: restart iptables" away, and so forth.

It isn't that simple nor does Ansible handle this case. The rule chains
are additive across roles and order is important.
The basic process is:
- Base role: Setup firewall and insert base rules
- Role1 : add rules
- Role 2: add rules
- Playbook is done. Add closing rules. Restart and save iptables. This
spans inventory groups in addition to roles.

Yep this is exactly the point I'm making as why we shouldn't just drill
holes.

I think we're getting somewhere here.

Have you looked at the 'assemble' module for assembling a configuration
file out of fragments? This isn't ideal in this case nor generalically
applicable to Galaxy, but may be closer to what you are wanting.

Maybe there is another way to do it. That's fine. The point is that the
roles be able to add their own custom rules without having to understand
what other roles are doing. This is a common Unix idiom where there is a
"conf.d" directory and applications place custom file snippets in it. If
order is important then they are often named 01file, 02file, etc. This is
the pattern I am arguing for implementing as an Ansible module.

assemble is there to provide conf.d to systems that don't have it.

http://docs.ansible.com/assemble_module.html

I'm still against applying that generically for firewall setup to all
galaxy roles and believe people should make their own choices in this
regard.

I just wanted to expand on what Michael was saying about using assemble:

For each role have a template snippet of firewall configuration and push it into /etc/iptables/snippets. Then in a final role that gets added after all other roles (call it a chinstrap role), use the assemble module to merge all the iptables snippets into a single iptables file and use a notify to restart iptables when the assembled file has changed.

  • James

Plus, the aforementioned groups that want to maintain their own firewall configurations, which we suggest, and you can see an example of here:

https://github.com/ansible/ansible-examples/blob/master/lamp_haproxy/roles/common/templates/iptables.j2

I disagree with the approach taken in this link because I do not want to use the persistence file (ferm or ufw are much better) and because I don’t think their use of if/then is good design (see http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html). But this isn’t really important.

I think the ferm approach used here is the best approach: http://wiki.gema-soft.de/doku.php?id=it-administration:tools:ansible:ferm

Having each role add its own ferm snippet maintains encapsulation (no hard to maintain if/then blocks) and uses a proper firewall management tool. The problem is that since there is no global notification there is no way to signal to Ansible to run the handler at the end. That is why I asked about a module.

A chinstrap role that James mentions could work but it has no way of knowing that a change has taken place (ie., a new snippet was added, changed, or removed). At least none that I know of. The alternative is simply to make the chinstrap role at the end always fire which would work but you then lose idempotency.

A global notify would enable this. This is at least one case where it is needed. There are probably more cases in which a final run cleanup step could be useful. In fact, global handlers would have come in useful many times in my experience.

There are too many ways of maintaining a firewall, across all types of admins, OS, etc.

However, I make use of a firewall role, I set ports when I attach it to a host, and then, I made an executive decision that the 'app' I'm configuring will use a particular type of firewall software.

However, I still allow for some variant across at least debian and redhat; I use a when: in my role, and key off ansible_pkg_mgr(== 'yum' or 'apt').

I really don't think it would be possible to have a completely generic 'firewall' module that handles all cases.

With a chinstrap role, if there are no changes to the snippets there is no
change in the result of the assemble, thus no handler would be fired. So it
is indeed idempotent. It is true that the role would always have to run.
Many people use a "common" role that runs before other roles, think of
this as the antithesis.

- James