Puppet module for managing firewalld
This module manages firewalld, the userland interface that replaces
iptables and ships with RHEL7+. The module manages firewalld itself as
well as providing types and providers for managing firewalld zones,
policies, ports, and rich rules.
Latest versions of this module are only supported on Puppet
7.0+.
class { 'firewalld': }
package
: Name of the package to install (default firewalld)package_ensure
: Default ‘installed’, can be any supported ensure type forconfig_package
: Name of the GUI package, default firewall-configinstall_gui
: Whether or not to install the config_package (default: false)service_ensure
: Whether the service should be running or not (default: running)service_enable
: Whether to enable the servicedefault_zone
: Optional, set the default zone for interfaces (default: undef)firewall_backend
: Optional, set the firewall backend for firewalld (default:default_service_zone
: Optional, set the default zone for services (default: undef)default_port_zone
: Optional, set the default zone for ports (default: undef)default_port_protocol
: Optional, set the default protocol for portslog_denied
: Optional, (firewalld-0.4.3.2-8+) Log denied packets, can be oneoff
, all
, multicast
, unicast
, broadcast
(default: undef)zones
: A hash of firewalld zones to configurepolicies
: A hash of firewalld policies to configureports
: A hash of firewalld ports to configureservices
: A hash of firewalld services to configurerich_rules
: A hash of firewalld rich rules to configurecustom_services
: A hash of firewalld customdirect_rules
: A hash of firewalld direct rules todirect_chains
: A hash of firewalld direct chainsdirect_passthroughs
: A hash of firewalld directpurge_direct_rules
: True or false, whether to purge firewalld directpurge_direct_chains
: True or false, whether to purge firewalld directpurge_direct_passthroughs
: True or false, whether to purge firewalld directThe firewalld module contains types and providers to manage zones,
services, ports, and rich rules by interfacing with the firewall-cmd
command. The following types are currently supported. Note that all
zone, service, port, and rule management is done in --permanent
mode, and a complete reload will be triggered anytime something
changes.
This module supports a number of resource types
Note, it is always recommended to include the ::firewalld
class if
you are going to use any of these resources from another Puppet class
(eg: a profile) as it sets up the relationships between thefirewalld
service resource and the exec resource to reload the
firewall upon change. Without the firewalld
class included then the
firewall will not be reloaded upon change. The recommended pattern is
to put all resources into hiera and let the firewalld
class set them
up. Examples of both forms are presented for the resource types below.
Firewalld zones can be managed with the firewalld_zone
resource type.
Example in Class:
firewalld_zone { 'restricted':
ensure => present,
target => '%%REJECT%%',
purge_rich_rules => true,
purge_services => true,
purge_ports => true,
}
Example in Hiera:
firewalld::zones:
restricted:
ensure: present
target: '%%REJECT%%'
purge_rich_rules: true
purge_services: true
purge_ports: true
target
: Specify the target of the zone.interfaces
: An array of interfaces for this zonesources
: An array of sources for the zoneprotocols
: An array of protocols for the zoneicmp_blocks
: An array of ICMP blocks for the zonemasquerade
: If set to true
or false
specifies whether or notpurge_rich_rules
: Optional, and defaulted to false. When true anypurge_services
: Optional, and defaulted to false. When true anypurge_ports
: Optional, and defaulted to false. When true anyFirewalld policies can be managed with the firewalld_policy
resource type.
Example in Class:
firewalld_policy { 'anytorestricted':
ensure => present,
target => '%%REJECT%%',
ingress_zones => ['ANY'],
egress_zones => ['restricted'],
purge_rich_rules => true,
purge_services => true,
purge_ports => true,
}
Example in Hiera:
firewalld::policies:
anytorestricted:
ensure: present
target: '%%REJECT%%'
ingress_zones:
- 'ANY'
egress_zones:
- 'restricted'
purge_rich_rules: true
purge_services: true
purge_ports: true
target
: Specify the target of the policy.ingress_zones
: An array of ingress zones for this policy.egress_zones
: An array of egress zones for this policy.priority
: A non zero integer specifying the priority of thisicmp_blocks
: An array of ICMP blocks for the policymasquerade
: If set to true
or false
specifies whether or notpurge_rich_rules
: Optional, and defaulted to false. When true anypurge_services
: Optional, and defaulted to false. When true anypurge_ports
: Optional, and defaulted to false. When true anyFirewalld rich rules are managed using the firewalld_rich_rule
resource type
Exactly one of the zone
or policy
parameters must be given
firewalld_rich_rules will autorequire
the firewalld_zone specified
in the zone
parameter or the firewalld_policy specified in thepolicy
parameter so there is no need to add dependencies for this
Example in Class:
firewalld_rich_rule { 'Accept SSH from barny':
ensure => present,
zone => 'restricted',
source => '192.168.1.2/32',
service => 'ssh',
action => 'accept',
}
Example in Hiera:
firewalld::rich_rules:
'Accept SSH from barny':
ensure: present
zone: restricted
source: '192.168.1.2/32'
service: 'ssh'
action: 'accept'
zone
: (Optional) Name of the zone this rich rule belongs to
policy
: (Optional) Name of the policy this rich rule belongs to
family
: Protocol family, defaults to ipv4
source
: Source address information. This can be a hash containing
the keys address or ipset
and invert
, or a string containing
just the IP address
source => '192.168.2.1',
source => { 'address' => '192.168.1.1', 'invert' => true }
source => { 'ipset' => 'whitelist', 'invert' => true }
source => { 'ipset' => 'blacklist' }
dest
: Destination address information. This can be a hash
containing the keys address or ipset
and invert
, or a string
containing just the IP address
dest => '192.168.2.1',
dest => { 'address' => '192.168.1.1', 'invert' => true }
dest => { 'ipset' => 'whitelist', 'invert' => true }
dest => { 'ipset' => 'blacklist' }
log
: When set to true
will enable logging, optionally this can
be hash with prefix
, level
and limit
log => { 'level' => 'debug', 'prefix' => 'foo' },
log => true,
audit
: When set to true
will enable auditing, optionally this
can be hash with limit
audit => { 'limit' => '3/s' },
audit => true,
action
: A string containing the action accept
, reject
ordrop
. For reject
it can be optionally supplied as a hash
containing type
action => 'accept'
action => { 'action' => 'reject', 'type' => 'bad' }
The following paramters are the element of the rich rule, only one
may be used.
service
: Name of the service
protocol
: Protocol of the rich rule
port
: A hash containing port
and protocol
values
port => {
'port' => 80,
'protocol' => 'tcp',
},
icmp_block
: Specify an icmp-block
for the rule
masquerade
: Set to true
or false
to enable masquerading
forward_port
: Set forward-port, this should be a hash containingport
,protocol
,to_port
,to_addr
forward_port => {
'port' => '8080',
'protocol' => 'tcp',
'to_addr' => '10.2.1.1',
'to_port' => '8993'
},
The firewalld_custom_service
defined type creates and manages
custom services. It makes the service usable by firewalld, but does
not add it to any zones. To do that, use the firewalld::service type.
Example in Class:
firewalld_custom_service{'puppet':
short => 'puppet',
description => 'Puppet Client access Puppet Server',
ports => [
{
'port' => '8140',
'protocol' => 'tcp',
},
{
'port' => '8140',
'protocol' => 'udp',
},
],
module => ['nf_conntrack_netbios_ns'],
'ipv4_destination' => '127.0.0.1',
'ipv6_destination' => '::1'
}
Example in Hiera:
firewalld::custom_services:
puppet:
short: 'puppet'
description: 'Puppet Client access Puppet Server'
ports:
- port: 8140
protocol: 'tcp'
module: 'nf_conntrack_netbios_ns'
ipv4_destination: '127.0.0.1'
ipv6_destination: '::1'
This resource will create the following XML service definition in
/etc/firewalld/services/XZY.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>puppet</short>
<description>Puppet Client access Puppet Server</description>
<port protocol="tcp" port="8140" ></port>
<port protocol="udp" port="8140" ></port>
<module name="nf_conntrack_netbios_ns"></module>
<destination ipv4="127.0.0.1" ipv6="::1"></destination>
</service>
and you will also see ‘puppet’ in the service list when you issuefirewall-cmd --permanent --get-services
short
: (namevar) The short name of the service (what you see in
the firewalld command line output)
description
: (Optional) A short description of the service
ports
: (Optional) The protocol / port definitions for this service.
Specified as an array of hashes, where each hash defines a protocol
and/or port associated with this service. Each hash requires both
port and protocol keys, even if the value is an empty string.
Specifying a port only works for TCP & UDP, otherwise leave it empty
and the entire protocol will be allowed. Valid protocols are tcp,
udp, or any protocol defined in /etc/protocols
ports => [{'port' => '1234', 'protocol' => 'tcp'}],
ports => [{'port' => '4321', 'protocol' => 'udp'}, {'protocol' => 'rdp'}],
The ports
parameter can also take a range of ports separated by a
colon or a dash (colons are replaced by dashes), for example:
ports => [ {'port' => '8000:8002', 'protocol' => 'tcp']} ]
will produce:
<port protocol="tcp" port="8000-8002" ></port>
protocols
: (Optional) An array of protocols allowed by the service
as defined in /etc/protocols.
protocols => ['ospf'],
module
: (Optional) An array of strings specifying netfilter kernel
helper modules associated with this service
ipv4_destination
: (Optional) A string specifying the destination
network as a network IP address (optional with /mask), or a plain IP
address.
The use of hostnames is possible but not recommended,
because these will only be resolved at service activation and
transmitted to the kernel.
ipv4_destination => '192.0.2.0/24',
ipv6_destination
: (Optional) A string specifying the destination
network as a network IP address (optional with /mask), or a plain IP
address.
The use of hostnames is possible but not recommended,
because these will only be resolved at service activation and
transmitted to the kernel.
ipv4_destination => '2001
:/32',
config_dir
: The location where the service definition XML files
will be stored. Defaults to /etc/firewalld/services
The firewalld_service
type is used to add or remove both built in
and custom services from zones.
Exactly one of the zone
or policy
parameters must be given.
firewalld_service will autorequire
the firewalld_zone specified in
the zone
parameter and the firewalld_custom_service specified in
the service
parameter, so there is no need to add dependencies for
this
Example in Class:
firewalld_service { 'Allow SSH from the external zone':
ensure => 'present',
service => 'ssh',
zone => 'external',
}
Example in Hiera:
firewalld::services:
'Allow SSH from the external zone':
ensure: present
service: ssh
zone: external
dhcp:
ensure: absent
service: dhcp
zone: public
dhcpv6-client:
ensure: present
service: dhcpv6-client
zone: public
service
: Name of the service to manage, defaults to the resource
name.
zone
: Name of the zone in which you want to manage the service,
defaults to parameter default_service_zone
of class firewalld
if
specified.
policy
: Name of the policy in which you want to manage the
service. Make sure to set zone
to unset
if you use this and have
specified default_service_zone
for class firewalld
.
ensure
: Whether to add (present
) or remove the service
(absent
), defaults to present
.
Firewalld IPsets (on supported versions of firewalld) can be managed
using the firewalld_ipset
resource type
Example:
firewalld_ipset { 'whitelist':
ensure => present,
entries => [ '192.168.0.1', '192.168.0.2' ]
}
Example in Hiera:
firewalld::ipsets:
whitelist:
entries:
- 192.168.0.1
- 192.168.0.2
entries
: An array of entries for the IPsettype
: Type of ipset (default: hash:ip
)options
: A hash of options for the IPset (eg:{ "family" => "inet6"}
)Note that type
and options
are parameters used when creating the
IPset and are not managed after creation - to change the type or
options of an ipset you must delete the existing ipset first.
Firewalld ports can be managed with the firewalld_port
resource
type.
Exactly one of the zone
or policy
parameters must be given.
firewalld_port will autorequire
the firewalld_zone specified in thezone
parameter so there is no need to add dependencies for this
Example:
firewalld_port { 'Open port 8080 in the public zone':
ensure => present,
zone => 'public',
port => 8080,
protocol => 'tcp',
}
Example in Hiera:
firewalld::ports:
'Open port 8080 in the public zone':
ensure: present
zone: public
port: 8080
protocol: 'tcp'
zone
: Name of the zone this port belongs to, defaults to parameterdefault_port_zone
of class firewalld
if specified.
policy
: Name of the policy this port belongs to. Make sure to setzone
to unset
if you use this and have specifieddefault_port_zone
for class firewalld
.
port
: The port to manage, defaults to the resource name.
protocol
: The protocol this port uses, e.g. tcp
or udp
,
defaults to parameter default_port_protocol
of class firewalld
if specified.
ensure
: Whether to add (present
) or remove the service
(absent
), defaults to present
.
Direct chains can be managed with the firewalld_direct_chain
type
firewalld_direct_chain {'Add custom chain LOG_DROPS':
name => 'LOG_DROPS',
ensure => present,
inet_protocol => 'ipv4',
table => 'filter',
}
The title can also be mapped to the types namevars using a colon
delimited string, so the above can also be represented as
firewalld_direct_chain { 'ipv4:filter:LOG_DROPS':
ensure => present,
}
firewalld::direct_chains:
'Add custom chain LOG_DROPS':
name: LOG_DROPS
ensure: present
inet_protocol: ipv4
table: filter
name
: name of the chain, eg LOG_DROPS
(namevar)inet_protocol
: ipv4, ipv6 or eb, defaults to ipv4 (namevar)table
: The table (eg: filter) to apply the chain (namevar)Direct rules can be applied using the firewalld_direct_rule
type
firewalld_direct_rule {'Allow outgoing SSH connection':
ensure => 'present',
inet_protocol => 'ipv4',
table => 'filter',
chain => 'OUTPUT',
priority => 1,
args => '-p tcp --dport=22 -j ACCEPT',
}
firewalld::direct_rules:
'Allow outgoing SSH connection':
ensure: present
inet_protocol: ipv4
table: filter
chain: OUTPUT
priority: 1
args: '-p tcp --dport=22 -j ACCEPT'
name
: Resource name in Puppetensure
: present or absentinet_protocol
: ipv4, ipv6 or eb, defaults to ipv4table
: Table (eg: filter) which to apply the rulechain
: Chain (eg: OUTPUT) which to apply the rulepriority
: The priority number of the rule (e.g: 0, 1, 2, … 99)args
: Any iptables, ip6tables and ebtables command line argumentsDirect passthroughs can be applied using the firewalld_direct_passthrough
type
firewalld_direct_passthrough {'Forward traffic from OUTPUT to OUTPUT_filter':
ensure => 'present',
inet_protocol => 'ipv4',
args => '-A OUTPUT -j OUTPUT_filter'
}
firewalld::direct_passthroughs:
'Forward traffic from OUTPUT to OUTPUT_filter':
ensure: present
inet_protocol: ipv4
args: '-A OUTPUT -j OUTPUT_filter'
name
: Resource name in Puppetensure
: present or absentinet_protocol
: ipv4, ipv6 or eb, defaults to ipv4args
: Name of the passthroughhrough to add (e.g:Unit tests can be executed by running the following commands:
bundle install
bundle exec rake spec
Acceptance tests are performed using
Beaker and require
Vagrant and
VirtualBox to run successfully.
It is HIGHLY RECOMMENDED that you use the upstream Vagrant package
and not one from your OS provider.
To run the acceptance tests:
bundle install
bundle exec rake beaker
To leave the Vagrant hosts running on failure for debugging:
BEAKER_destroy=onpass bundle exec rake beaker
cd .vagrant/beaker_vagrant_files/default.yml
vagrant ssh <host>