2.7. Configuring the Firewall

The web server requires an open port so people can access the pages hosted on our web server. The open problem is that different versions of Red Hat Enterprise Linux uses different methods for controlling the firewall. For Red Hat Enterprise Linux 6 and below, we use iptables. For Red Hat Enterprise Linux 7, we use firewalld.
This decision is something Puppet handles using conditional logic and system facts. For this step, we add a statement to check the operating system and run the appropriate firewall commands.
Add the following code inside your mymodule::http class:
  if $operatingsystemmajrelease <= 6 {
    exec { 'iptables':
      command => "iptables -I INPUT 1 -p tcp -m multiport --ports ${httpd_port} -m comment --comment 'Custom HTTP Web Host' -j ACCEPT && iptables-save > /etc/sysconfig/iptables",
      path => "/sbin",
      refreshonly => true,
      subscribe => Package['httpd'],
    }
    service { 'iptables':
      ensure => running,
      enable => true,
      hasrestart => true,
      subscribe => Exec['iptables'],
    }
  }
  elsif $operatingsystemmajrelease == 7 {
    exec { 'firewall-cmd':
      command => "firewall-cmd --zone=public --add-port=${httpd_port}/tcp --permanent",
      path => "/usr/bin/",
      refreshonly => true,
      subscribe => Package['httpd'],
    }
    service { 'firewalld':
      ensure => running,
      enable => true,
      hasrestart => true,
      subscribe => Exec['firewall-cmd'],
    }
  }
This code performs the following:
  • Use the operatingsystemmajrelease fact to determine whether the operating system is Red Hat Enterprise Linux 6 or 7.
  • If using Red Hat Enterprise Linux 6, declare an executable (exec) resource that runs iptables and iptables-save to add a permanent firewall rule. The httpd_port variable is used in-line to define the port to open. After the exec resource completes, we trigger a refresh of the iptables service. To achieve this, we define a service resource that includes the subscribe attribute. This attribute checks if any there are any changes to another resource and, if so, performs a refresh. In this case, it checks the iptables executable resource.
  • If using Red Hat Enterprise Linux 7, declare a similar executable resource that runs firewall-cmd to add a permanent firewall rule. The httpd_port variable is also used in-line to define the port to open. After the exec resource completes, we trigger a refresh of the firewalld service but with a subscribe attribute pointing to the firewall-cmd executable resource.
  • The code for both firewall executable resources contains refreshonly => true and subscribe => Package['httpd'] attributes. This ensures the firewall commands only run after the httpd installs. Without these attributes, subsequent runs will add multiple instances of the same firewall rule.
Run the puppet apply command again to test the changes to our module. The following example is a test of Red Hat Enterprise Linux 6:
# puppet apply mymodule/tests/init.pp --noop
Warning: Config file /etc/puppet/hiera.yaml not found, using Hiera defaults
Notice: Compiled catalog for puppet.example.com in environment production in 0.82 seconds
Notice: /Stage[main]/Mymodule::Httpd/Exec[iptables]/returns: current_value notrun, should be 0 (noop)
Notice: /Stage[main]/Mymodule::Httpd/Service[iptables]: Would have triggered 'refresh' from 1 events
...
The highlighted lines show the execution of the firewall rule creation and the subsequent service refresh as a result of the subscribe attribute.

Important

This configuration serves only as an example of using conditional statements. If you aim to manage multiple firewall rules for your system in the future, it is recommended to create a custom resource for firewalls. It is inadvisable to use executable resources to constantly chain many Bash commands.