684 changes: 684 additions & 0 deletions HISTORY.md

Large diffs are not rendered by default.

89 changes: 44 additions & 45 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,11 @@ Therefore, the run order is:
* Your rules (defined in code)
* The rules in `my_fw::post`

The rules in the `pre` and `post` classes are fairly general. These two classes ensure that you retain connectivity and that you drop unmatched packets appropriately. The rules you define in your manifests are likely specific to the applications you run.
The rules in the `pre` and `post` classes are fairly general. These two classes ensure that you retain connectivity and that you drop unmatched packets appropriately. The rules you define in your manifests are likely to be specific to the applications you run.

1.) Add the `pre` class to my_fw/manifests/pre.pp. Your pre.pp file should contain any default rules to be applied first. The rules in this class should be added in the order you want them to run.2.
~~~puppet
1. Add the `pre` class to `my_fw/manifests/pre.pp`, and any default rules to your pre.pp file first — in the order you want them to run.

~~~ puppet
class my_fw::pre {
Firewall {
require => undef,
Expand Down Expand Up @@ -101,11 +102,11 @@ The rules in the `pre` and `post` classes are fairly general. These two classes
}
~~~

The rules in `pre` should allow basic networking (such as ICMP and TCP) and ensure that existing connections are not closed.
The rules in `pre` allow basic networking (such as ICMP and TCP) and ensure that existing connections are not closed.

2.) Add the `post` class to my_fw/manifests/post.pp and include any default rules to be applied last.
2. Add the `post` class to `my_fw/manifests/post.pp` and include any default rules — apply these last.

~~~puppet
~~~ puppet
class my_fw::post {
firewall { '999 drop all':
proto => 'all',
Expand All @@ -117,7 +118,7 @@ The rules in the `pre` and `post` classes are fairly general. These two classes

Alternatively, the [firewallchain](#type-firewallchain) type can be used to set the default policy:

~~~puppet
~~~ puppet
firewallchain { 'INPUT:filter:IPv4':
ensure => present,
policy => drop,
Expand All @@ -131,42 +132,42 @@ The rules you create here are helpful if you don’t have any existing rules; th

Rules are persisted automatically between reboots, although there are known issues with ip6tables on older Debian/Ubuntu distributions. There are also known issues with ebtables.

1.) In site.pp or another top-scope file, add the following code to set up a metatype to purge unmanaged firewall resources. This will clear any existing rules and make sure that only rules defined in Puppet exist on the machine.
1. In site.pp or another top-scope file, add the following code to set up a metatype to purge unmanaged firewall resources. This will clear any existing rules and make sure that only rules defined in Puppet exist on the machine.

~~~puppet
~~~ puppet
resources { 'firewall':
purge => true,
}
~~~

To purge unmanaged firewall chains, also add:
To purge unmanaged firewall chains, add:

~~~puppet
~~~ puppet
resources { 'firewallchain':
purge => true,
}
~~~

**Note** - If there are unmanaged rules in unmanaged chains, it will take two Puppet runs before the firewall chain is purged. This is different than the `purge` parameter available in `firewallchain`.
**Note** - If there are unmanaged rules in unmanaged chains, it will take two Puppet runs for the firewall chain to be purged. This is different than the `purge` parameter available in `firewallchain`.

2.) Use the following code to set up the default parameters for all of the firewall rules you will establish later. These defaults will ensure that the `pre` and `post` classes are run in the correct order to avoid locking you out of your box during the first Puppet run.
2. Use the following code to set up the default parameters for all of the firewall rules that you will establish later. These defaults will ensure that the `pre` and `post` classes are run in the correct order and avoid locking you out of your box during the first Puppet run.

~~~puppet
~~~ puppet
Firewall {
before => Class['my_fw::post'],
require => Class['my_fw::pre'],
}
~~~

3.) Then, declare the `my_fw::pre` and `my_fw::post` classes to satisfy dependencies. You can declare these classes using an External Node Classifier or the following code:
3. Declare the `my_fw::pre` and `my_fw::post` classes to satisfy dependencies. You can declare these classes using an external node classifier or the following code:

~~~puppet
~~~ puppet
class { ['my_fw::pre', 'my_fw::post']: }
~~~

4.) Include the `firewall` class to ensure the correct packages are installed.
4. Include the `firewall` class to ensure the correct packages are installed:

~~~puppet
~~~ puppet
class { 'firewall': }
~~~

Expand Down Expand Up @@ -196,7 +197,7 @@ In iptables, the title of the rule is stored using the comment feature of the un

Basic accept ICMP request example:

~~~puppet
~~~ puppet
firewall { '000 accept all icmp requests':
proto => 'icmp',
action => 'accept',
Expand All @@ -205,7 +206,7 @@ firewall { '000 accept all icmp requests':

Drop all:

~~~puppet
~~~ puppet
firewall { '999 drop all other requests':
action => 'drop',
}
Expand All @@ -215,7 +216,7 @@ firewall { '999 drop all other requests':

IPv6 rules can be specified using the _ip6tables_ provider:

~~~puppet
~~~ puppet
firewall { '006 Allow inbound SSH (v6)':
dport => 22,
proto => tcp,
Expand All @@ -235,7 +236,7 @@ remain close to the services managed by the profile.

This is an example of firewall rules in a profile:

~~~puppet
~~~ puppet
class profile::apache {
include apache
apache::vhost { 'mysite': ensure => present }
Expand All @@ -256,7 +257,7 @@ Parameters that understand inversion are: connmark, ctstate, destination, dport,

Examples:

~~~puppet
~~~ puppet
firewall { '001 disallow esp protocol':
action => 'accept',
proto => '! esp',
Expand All @@ -276,7 +277,7 @@ firewall { '002 drop NEW external website packets with FIN/RST/ACK set and SYN u

You can apply firewall rules to specific nodes. Usually, you should put the firewall rule in another class and apply that class to a node. Apply a rule to a node as follows:

~~~puppet
~~~ puppet
node 'some.node.com' {
firewall { '111 open port 111':
dport => 111,
Expand All @@ -286,7 +287,7 @@ node 'some.node.com' {

You can also do more complex things with the `firewall` resource. This example sets up static NAT for the source network 10.1.2.0/24:

~~~puppet
~~~ puppet
firewall { '100 snat for network foo2':
chain => 'POSTROUTING',
jump => 'MASQUERADE',
Expand All @@ -300,7 +301,7 @@ firewall { '100 snat for network foo2':

You can also change the TCP MSS value for VPN client traffic:

~~~puppet
~~~ puppet
firewall { '110 TCPMSS for VPN clients':
chain => 'FORWARD',
table => 'mangle',
Expand All @@ -315,7 +316,7 @@ firewall { '110 TCPMSS for VPN clients':

The following will mirror all traffic sent to the server to a secondary host on the LAN with the TEE target:

~~~puppet
~~~ puppet
firewall { '503 Mirror traffic to IDS':
proto => all,
jump => 'TEE',
Expand All @@ -327,7 +328,7 @@ firewall { '503 Mirror traffic to IDS':

The following example creates a new chain and forwards any port 5000 access to it.

~~~puppet
~~~ puppet
firewall { '100 forward to MY_CHAIN':
chain => 'INPUT',
jump => 'MY_CHAIN',
Expand All @@ -346,7 +347,7 @@ firewall { '100 my rule':

Setup NFLOG for a rule.

~~~puppet
~~~ puppet
firewall {'666 for NFLOG':
proto => 'all',
jump => 'NFLOG',
Expand Down Expand Up @@ -680,7 +681,7 @@ If Puppet is managing the iptables or iptables-persistent packages, and the prov

* `name`: The canonical name of the rule. This name is also used for ordering, so make sure you prefix the rule with a number. For example:

~~~puppet
~~~ puppet
firewall { '000 this runs first':
# this rule will run first
}
Expand Down Expand Up @@ -739,7 +740,7 @@ If Puppet is managing the iptables or iptables-persistent packages, and the prov

* `recent`: Enable the recent module. Valid values are: 'set', 'update', 'rcheck', or 'remove'. For example:

~~~puppet
~~~ puppet
# If anyone's appeared on the 'badguy' blacklist within
# the last 60 seconds, drop their traffic, and update the timestamp.
firewall { '100 Drop badguy traffic':
Expand Down Expand Up @@ -847,7 +848,7 @@ If Puppet is managing the iptables or iptables-persistent packages, and the prov

* `tosource`: When using `jump => 'SNAT'`, you can specify the new source address using this parameter. Requires the `snat` feature.

* `to`: When using `jump => 'NETMAP'`, you can specify a source or destination subnet to nat to. Requires the `netmap` feature`.
* `to`: When using `jump => 'NETMAP'`, you can specify a source or destination subnet to nat to. Requires the `netmap` feature.

* `uid`: UID or Username owner matching rule. Accepts a string argument only, as iptables does not accept multiple uid in a single statement. Requires the `owner` feature.

Expand Down Expand Up @@ -877,7 +878,7 @@ Currently this type supports only iptables, ip6tables, and ebtables on Linux. It
* `ignore`: Regex to perform on firewall rules to exempt unmanaged rules from purging (when enabled). This is matched against the output of iptables-save. This can be a single regex or an array of them. To support flags, use the ruby inline flag mechanism: a regex such as '/foo/i' can be written as '(?i)foo' or '(?i:foo)'. Only when purge is 'true'.

Full example:
~~~puppet
~~~ puppet
firewallchain { 'INPUT:filter:IPv4':
purge => true,
ignore => [
Expand Down Expand Up @@ -910,7 +911,7 @@ Currently this type supports only iptables, ip6tables, and ebtables on Linux. It

**Note** This `purge` is purging unmanaged rules in a firewall chain, not unmanaged firewall chains. To purge unmanaged firewall chains, use the following instead.

~~~puppet
~~~ puppet
resources { 'firewallchain':
purge => true,
}
Expand All @@ -930,6 +931,8 @@ Retrieves the version of iptables-persistent from your OS. This is a Debian/Ubun

## Limitations

For an extensive list of supported operating systems, see [metadata.json](https://github.com/puppetlabs/puppetlabs-firewall/blob/master/metadata.json)

### SLES

The `socket` parameter is not supported on SLES. In this release it will cause
Expand All @@ -943,11 +946,6 @@ when the "Unbreakable" kernel is used. These may function correctly when using
the stock RedHat kernel instead. Declaring either of these parameters on an
unsupported system will result in iptable rules failing to apply.

### Debian 8 Support

As Puppet Enterprise itself does not yet support Debian 8, use of this module with Puppet Enterprise under a Debian 8
system should be regarded as experimental.

## Passing firewall parameter values as arrays with `firewall_multi` module

You might sometimes need to pass arrays, such as arrays of source or destination addresses, to some parameters in contexts where iptables itself does not allow arrays.
Expand Down Expand Up @@ -1016,13 +1014,14 @@ Make sure you have:

Install the necessary gems:

bundle install
~~~ text
bundle install
~~~

And run the tests from the root of the source code:

rake test

If you have a copy of Vagrant 1.1.0 you can also run the system tests:
~~~ text
bundle exec rake parallel_spec
~~~

RS_SET=ubuntu-1404-x64 rspec spec/acceptance
RS_SET=centos-64-x64 rspec spec/acceptance
See also `.travis.yml` for information on running the acceptance and other tests.
74 changes: 73 additions & 1 deletion Rakefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,75 @@
require 'puppetlabs_spec_helper/rake_tasks'
require 'puppet-syntax/tasks/puppet-syntax'
require 'puppet_blacksmith/rake_tasks'
require 'puppet_blacksmith/rake_tasks' if Bundler.rubygems.find_name('puppet-blacksmith').any?
require 'github_changelog_generator/task' if Bundler.rubygems.find_name('github_changelog_generator').any?

def changelog_user
return unless Rake.application.top_level_tasks.include? "changelog"
returnVal = "puppetlabs" || JSON.load(File.read('metadata.json'))['author']
raise "unable to find the changelog_user in .sync.yml, or the author in metadata.json" if returnVal.nil?
puts "GitHubChangelogGenerator user:#{returnVal}"
returnVal
end

def changelog_project
return unless Rake.application.top_level_tasks.include? "changelog"
returnVal = nil || JSON.load(File.read('metadata.json'))['name']
raise "unable to find the changelog_project in .sync.yml or the name in metadata.json" if returnVal.nil?
puts "GitHubChangelogGenerator project:#{returnVal}"
returnVal
end

def changelog_future_release
return unless Rake.application.top_level_tasks.include? "changelog"
returnVal = JSON.load(File.read('metadata.json'))['version']
raise "unable to find the future_release (version) in metadata.json" if returnVal.nil?
puts "GitHubChangelogGenerator future_release:#{returnVal}"
returnVal
end

PuppetLint.configuration.send('disable_relative')

if Bundler.rubygems.find_name('github_changelog_generator').any?
GitHubChangelogGenerator::RakeTask.new :changelog do |config|
raise "Set CHANGELOG_GITHUB_TOKEN environment variable eg 'export CHANGELOG_GITHUB_TOKEN=valid_token_here'" if Rake.application.top_level_tasks.include? "changelog" and ENV['CHANGELOG_GITHUB_TOKEN'].nil?
config.user = "#{changelog_user}"
config.project = "#{changelog_project}"
config.future_release = "#{changelog_future_release}"
config.exclude_labels = ['maintenance']
config.header = "# Change log\n\nAll notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org)."
config.add_pr_wo_labels = true
config.issues = false
config.merge_prefix = "### UNCATEGORIZED PRS; GO LABEL THEM"
config.configure_sections = {
"Changed" => {
"prefix" => "### Changed",
"labels" => ["backwards-incompatible"],
},
"Added" => {
"prefix" => "### Added",
"labels" => ["feature", "enhancement"],
},
"Fixed" => {
"prefix" => "### Fixed",
"labels" => ["bugfix"],
},
}
end
else
desc 'Generate a Changelog from GitHub'
task :changelog do
raise <<EOM
The changelog tasks depends on unreleased features of the github_changelog_generator gem.
Please manually add it to your .sync.yml for now, and run `pdk update`:
---
Gemfile:
optional:
':development':
- gem: 'github_changelog_generator'
git: 'https://github.com/skywinder/github-changelog-generator'
ref: '20ee04ba1234e9e83eb2ffb5056e23d641c7a018'
condition: "Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.2.2')"
EOM
end
end

2 changes: 1 addition & 1 deletion lib/facter/iptables_persistent_version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Facter.add(:iptables_persistent_version) do
confine operatingsystem: %w[Debian Ubuntu]
confine operatingsystem: ['Debian', 'Ubuntu']
setcode do
# Throw away STDERR because dpkg >= 1.16.7 will make some noise if the
# package isn't currently installed.
Expand Down
17 changes: 14 additions & 3 deletions lib/puppet/provider/firewall/iptables.rb
Original file line number Diff line number Diff line change
Expand Up @@ -393,12 +393,12 @@ def self.rule_to_hash(line, table, counter)
values = values.gsub(%r{-m set --match-set (!\s+)?\S* \S* }, '')
values.insert(ind, "-m set --match-set \"#{sets.join(';')}\" ")
end
# the actual rule will have the ! mark before the option.
values = values.gsub(%r{(!)\s*(-\S+)\s*(\S*)}, '\2 "\1 \3"')
# we do a similar thing for negated address masks (source and destination).
values = values.gsub(%r{(?<=\s)(-\S+) (!)\s?(\S*)}, '\1 "\2 \3"')
# fix negated physdev rules
values = values.gsub(%r{-m physdev ! (--physdev-is-\S+)}, '-m physdev \1 "!"')
# the actual rule will have the ! mark before the option.
values = values.gsub(%r{(!)\s*(-\S+)\s*(\S*)}, '\2 "\1 \3"')
# The match extension for tcp & udp are optional and throws off the @resource_map.
values = values.gsub(%r{(?!-m tcp --tcp-flags)-m (tcp|udp) }, '')
# There is a bug in EL5 which puts 2 spaces before physdev, so we fix it
Expand Down Expand Up @@ -637,7 +637,7 @@ def self.rule_to_hash(line, table, counter)

# If the jump parameter is set to one of: ACCEPT, REJECT or DROP then
# we should set the action parameter instead.
if %w[ACCEPT REJECT DROP].include?(hash[:jump])
if ['ACCEPT', 'REJECT', 'DROP'].include?(hash[:jump])
hash[:action] = hash[:jump].downcase
hash.delete(:jump)
end
Expand All @@ -661,6 +661,17 @@ def update_args
def delete_args
# Split into arguments
line = properties[:line].gsub(%r{^\-A }, '-D ').split(%r{\s+(?=(?:[^"]|"[^"]*")*$)}).map { |v| v.gsub(%r{^"}, '').gsub(%r{"$}, '') }
if self.class.instance_variable_get(:@protocol) == 'IPv6' && properties[:proto] == 'all'
#
# There is currently a bug in ip6tables where delete rules do not match rules using any protocol
# if '-p' all is missing.
#
# https://bugzilla.netfilter.org/show_bug.cgi?id=1015
#
# This check looks for this case, and adds '-p all' to the rule for ipv6.
#
line = line.concat ['-p', 'all']
end
line.unshift('-t', properties[:table])
end

Expand Down
15 changes: 6 additions & 9 deletions lib/puppet/type/firewall.rb
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ def should_to_s(value)
PUPPETCODE
end

if %w[accept reject drop].include?(value.downcase)
if ['accept', 'reject', 'drop'].include?(value.downcase)
raise ArgumentError, <<-PUPPETCODE
Jump destination should not be one of ACCEPT, REJECT or DROP. Use
the action property instead.
Expand Down Expand Up @@ -522,7 +522,7 @@ def should_to_s(value)
PUPPETCODE
end

if %w[accept reject drop].include?(value.downcase)
if ['accept', 'reject', 'drop'].include?(value.downcase)
raise ArgumentError, <<-PUPPETCODE
Goto destination should not be one of ACCEPT, REJECT or DROP. Use
the action property instead.
Expand Down Expand Up @@ -1059,10 +1059,7 @@ def insync?(is)
PUPPETCODE
# iptables uses the cisco DSCP classes as the basis for this flag. Values may be found here:
# 'http://www.cisco.com/c/en/us/support/docs/quality-of-service-qos/qos-packet-marking/10103-dscpvalues.html'
valid_codes = %w[
af11 af12 af13 af21 af22 af23 af31 af32 af33 af41
af42 af43 cs1 cs2 cs3 cs4 cs5 cs6 cs7 ef
]
valid_codes = ['af11', 'af12', 'af13', 'af21', 'af22', 'af23', 'af31', 'af32', 'af33', 'af41', 'af42', 'af43', 'cs1', 'cs2', 'cs3', 'cs4', 'cs5', 'cs6', 'cs7', 'ef']
munge do |value|
unless valid_codes.include? value.downcase
raise ArgumentError, "#{value} is not a valid DSCP Class"
Expand Down Expand Up @@ -1720,7 +1717,7 @@ def should_to_s(value)
unless protocol.nil?
table = value(:table)
[value(:chain), value(:jump)].each do |chain|
reqs << "#{chain}:#{table}:#{protocol}" unless chain.nil? || (%w[INPUT OUTPUT FORWARD].include?(chain) && table == :filter)
reqs << "#{chain}:#{table}:#{protocol}" unless chain.nil? || (['INPUT', 'OUTPUT', 'FORWARD'].include?(chain) && table == :filter)
end
end

Expand All @@ -1732,7 +1729,7 @@ def should_to_s(value)
autorequire(:package) do
case value(:provider)
when :iptables, :ip6tables
%w[iptables iptables-persistent iptables-services]
['iptables', 'iptables-persistent', 'iptables-services']
else
[]
end
Expand All @@ -1741,7 +1738,7 @@ def should_to_s(value)
autorequire(:service) do
case value(:provider)
when :iptables, :ip6tables
%w[firewalld iptables ip6tables iptables-persistent netfilter-persistent]
['firewalld', 'iptables', 'ip6tables', 'iptables-persistent', 'netfilter-persistent']
else
[]
end
Expand Down
4 changes: 2 additions & 2 deletions lib/puppet/type/firewallchain.rb
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@
autorequire(:package) do
case value(:provider)
when :iptables_chain
%w[iptables iptables-persistent iptables-services]
['iptables', 'iptables-persistent', 'iptables-services']
else
[]
end
Expand All @@ -167,7 +167,7 @@
autorequire(:service) do
case value(:provider)
when :iptables, :ip6tables
%w[firewalld iptables ip6tables iptables-persistent netfilter-persistent]
['firewalld', 'iptables', 'ip6tables', 'iptables-persistent', 'netfilter-persistent']
else
[]
end
Expand Down
14 changes: 7 additions & 7 deletions lib/puppet/util/firewall.rb
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ def persist_iptables(proto)
end

# RHEL 7 and newer also use systemd to persist iptable rules
if os_key == 'RedHat' && %w[RedHat CentOS Scientific SL SLC Ascendos CloudLinux PSBM OracleLinux OVS OEL XenServer VirtuozzoLinux]
if os_key == 'RedHat' && ['RedHat', 'CentOS', 'Scientific', 'SL', 'SLC', 'Ascendos', 'CloudLinux', 'PSBM', 'OracleLinux', 'OVS', 'OEL', 'XenServer', 'VirtuozzoLinux']
.include?(Facter.value(:operatingsystem)) && Facter.value(:operatingsystemrelease).to_i >= 7
os_key = 'Fedora'
end
Expand All @@ -205,24 +205,24 @@ def persist_iptables(proto)
when :RedHat
case proto.to_sym
when :IPv4
%w[/sbin/service iptables save]
['/sbin/service', 'iptables', 'save']
when :IPv6
%w[/sbin/service ip6tables save]
['/sbin/service', 'ip6tables', 'save']
end
when :Fedora
case proto.to_sym
when :IPv4
%w[/usr/libexec/iptables/iptables.init save]
['/usr/libexec/iptables/iptables.init', 'save']
when :IPv6
%w[/usr/libexec/iptables/ip6tables.init save]
['/usr/libexec/iptables/ip6tables.init', 'save']
end
when :Debian
case proto.to_sym
when :IPv4, :IPv6
if persist_ver && Puppet::Util::Package.versioncmp(persist_ver, '1.0') > 0
%w[/usr/sbin/service netfilter-persistent save]
['/usr/sbin/service', 'netfilter-persistent', 'save']
else
%w[/usr/sbin/service iptables-persistent save]
['/usr/sbin/service', 'iptables-persistent', 'save']
end
end
when :Debian_manual
Expand Down
38 changes: 24 additions & 14 deletions manifests/linux/redhat.pp
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,30 @@
}
}

service { $service_name:
ensure => $ensure,
enable => $enable,
hasstatus => true,
}
service { $service_name_v6:
ensure => $_ensure_v6,
enable => $_enable_v6,
hasstatus => true,
if ($::operatingsystem == 'Amazon') and (versioncmp($::operatingsystemmajrelease, '4') >= 0) {
service { $service_name:
ensure => $ensure,
enable => $enable,
hasstatus => true,
provider => systemd,
}
service { $service_name_v6:
ensure => $_ensure_v6,
enable => $_enable_v6,
hasstatus => true,
provider => systemd,
}
} else {
service { $service_name:
ensure => $ensure,
enable => $enable,
hasstatus => true,
}
service { $service_name_v6:
ensure => $_ensure_v6,
enable => $_enable_v6,
hasstatus => true,
}
}

file { "/etc/sysconfig/${service_name}":
Expand Down Expand Up @@ -106,11 +121,6 @@
case $::operatingsystem {
'CentOS': {
case $::operatingsystemrelease {
/^5\..*/: {
File["/etc/sysconfig/${service_name}"] { seluser => 'system_u', seltype => 'etc_t' }
File["/etc/sysconfig/${service_name_v6}"] { seluser => 'system_u', seltype => 'etc_t' }
}

/^6\..*/: {
File["/etc/sysconfig/${service_name}"] { seluser => 'unconfined_u', seltype => 'system_conf_t' }
File["/etc/sysconfig/${service_name_v6}"] { seluser => 'unconfined_u', seltype => 'system_conf_t' }
Expand Down
18 changes: 9 additions & 9 deletions metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "puppetlabs-firewall",
"version": "1.12.0",
"version": "1.13.0",
"author": "Puppet Labs",
"summary": "Manages Firewalls such as iptables",
"license": "Apache-2.0",
Expand All @@ -10,7 +10,7 @@
"dependencies": [
{
"name": "puppetlabs/stdlib",
"version_requirement": ">= 4.0.0 < 5.0.0"
"version_requirement": ">= 4.0.0 < 6.0.0"
}
],
"operatingsystem_support": [
Expand Down Expand Up @@ -40,7 +40,6 @@
{
"operatingsystem": "Scientific",
"operatingsystemrelease": [
"5",
"6",
"7"
]
Expand All @@ -55,16 +54,16 @@
{
"operatingsystem": "Debian",
"operatingsystemrelease": [
"6",
"7",
"8"
"8",
"9"
]
},
{
"operatingsystem": "Ubuntu",
"operatingsystemrelease": [
"14.04",
"16.04"
"16.04",
"18.04"
]
},
{
Expand All @@ -80,6 +79,7 @@
"version_requirement": ">= 4.7.0 < 6.0.0"
}
],
"template-url": "file:///opt/puppetlabs/pdk/share/cache/pdk-templates.git",
"template-ref": "1.3.2-0-g07678c8"
"template-url": "https://github.com/puppetlabs/pdk-templates",
"template-ref": "heads/master-0-g6a90b42",
"pdk-version": "1.7.0"
}
2 changes: 1 addition & 1 deletion spec/acceptance/firewall_iptmodules_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class { '::firewall': }
end

# iptables version 1.3.5 is not suppored by the ip6tables provider
if default['platform'] =~ %r{debian-7} || default['platform'] =~ %r{ubuntu-14\.04}
if default['platform'] =~ %r{ubuntu-14\.04}
describe 'ip6tables ipt_modules tests' do
context 'when all the modules with multiple args' do
pp3 = <<-PUPPETCODE
Expand Down
38 changes: 5 additions & 33 deletions spec/acceptance/firewall_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ class { '::firewall': }
end
end
%w[dst_type src_type].each do |type|
['dst_type', 'src_type'].each do |type|
describe type.to_s do
context 'when MULTICAST' do
pp26 = <<-PUPPETCODE
Expand Down Expand Up @@ -803,7 +803,7 @@ class { '::firewall': }
end
end
if default['platform'] !~ %r{el-5} && default['platform'] !~ %r{ubuntu-10\.04} && default['platform'] !~ %r{debian-6} && default['platform'] !~ %r{sles}
if default['platform'] !~ %r{el-5} && default['platform'] !~ %r{sles}
describe 'checksum_fill' do
context 'when virbr' do
pp38 = <<-PUPPETCODE
Expand Down Expand Up @@ -1256,7 +1256,7 @@ class { '::firewall': }
end
# ip6tables has limited `-m socket` support
if default['platform'] !~ %r{el-5} && default['platform'] !~ %r{ubuntu-10\.04} && default['platform'] !~ %r{debian-6} && default['platform'] !~ %r{sles}
if default['platform'] !~ %r{el-5} && default['platform'] !~ %r{sles}
describe 'socket' do
context 'when true' do
pp56 = <<-PUPPETCODE
Expand Down Expand Up @@ -1448,7 +1448,7 @@ class { '::firewall': }
end
# ip6tables only supports ipset, addrtype, and mask on a limited set of platforms
if default['platform'] =~ %r{el-7} || default['platform'] =~ %r{debian-7} || default['platform'] =~ %r{ubuntu-14\.04}
if default['platform'] =~ %r{el-7} || default['platform'] =~ %r{ubuntu-14\.04}
# ipset is really difficult to test, just testing on one platform
if default['platform'] =~ %r{ubuntu-14\.04}
describe 'ipset' do
Expand Down Expand Up @@ -1506,35 +1506,7 @@ class { '::firewall': }
end
end
# mask isn't supported on deb7
if default['platform'] !~ %r{debian-7}
describe 'mask' do
pp64 = <<-PUPPETCODE
class { '::firewall': }
firewall { '613 - test':
recent => 'update',
rseconds => 60,
rsource => true,
rname => 'test',
action => 'drop',
chain => 'FORWARD',
mask => 'ffff::',
provider => 'ip6tables',
}
PUPPETCODE
it 'applies' do
apply_manifest(pp64, catch_failures: true)
end

it 'contains the rule' do
shell('ip6tables-save') do |r|
expect(r.stdout).to match(%r{-A FORWARD -p tcp -m recent --update --seconds 60 --name test --mask ffff:: --rsource -m comment --comment "613 - test" -j DROP})
end
end
end
end

%w[dst_type src_type].each do |type|
['dst_type', 'src_type'].each do |type|
describe type.to_s do
context 'when MULTICAST' do
pp65 = <<-PUPPETCODE
Expand Down
2 changes: 1 addition & 1 deletion spec/acceptance/firewall_tee_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
ip6tables_flush_all_tables
end

if default['platform'] =~ %r{ubuntu-1404} || default['platform'] =~ %r{ubuntu-1204} || default['platform'] =~ %r{debian-7} || default['platform'] =~ %r{debian-8} || default['platform'] =~ %r{el-7}
if default['platform'] =~ %r{ubuntu-1404} || default['platform'] =~ %r{debian-8} || default['platform'] =~ %r{el-7}
describe 'tee_gateway' do
context 'when 10.0.0.2' do
pp1 = <<-PUPPETCODE
Expand Down
2 changes: 1 addition & 1 deletion spec/acceptance/firewall_time_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
ip6tables_flush_all_tables
end

if default['platform'] =~ %r{ubuntu-1404} || default['platform'] =~ %r{debian-7} || default['platform'] =~ %r{debian-8} || default['platform'] =~ %r{el-7}
if default['platform'] =~ %r{ubuntu-1404} || default['platform'] =~ %r{debian-8} || default['platform'] =~ %r{el-7}
describe 'time tests ipv4' do
context 'when set all time parameters' do
pp1 = <<-PUPPETCODE
Expand Down
18 changes: 9 additions & 9 deletions spec/fixtures/iptables/conversion_hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@
action: 'accept',
chain: 'INPUT',
destination: '1.1.1.1/32',
dport: %w[7061 7062],
dport: ['7061', '7062'],
ensure: :present,
line: '-A INPUT -s 1.1.1.1/32 -d 1.1.1.1/32 -p tcp -m multiport --dports 7061,7062 -m multiport --sports 7061,7062 -j ACCEPT -m comment --comment "000 allow foo"',
name: '000 allow foo',
proto: 'tcp',
provider: 'iptables',
source: '1.1.1.1/32',
sport: %w[7061 7062],
sport: ['7061', '7062'],
table: 'filter',
},
},
Expand Down Expand Up @@ -221,15 +221,15 @@
line: '-A INPUT -m state --state INVALID,RELATED,ESTABLISHED',
table: 'filter',
params: {
state: %w[ESTABLISHED INVALID RELATED],
state: ['ESTABLISHED', 'INVALID', 'RELATED'],
action: nil,
},
},
'ctstate_returns_sorted_values' => {
line: '-A INPUT -m conntrack --ctstate INVALID,RELATED,ESTABLISHED',
table: 'filter',
params: {
ctstate: %w[ESTABLISHED INVALID RELATED],
ctstate: ['ESTABLISHED', 'INVALID', 'RELATED'],
action: nil,
},
},
Expand Down Expand Up @@ -699,12 +699,12 @@
action: 'accept',
chain: 'INPUT',
destination: '1.1.1.1',
dport: %w[7061 7062],
dport: ['7061', '7062'],
ensure: :present,
name: '000 allow foo',
proto: 'tcp',
source: '1.1.1.1',
sport: %w[7061 7062],
sport: ['7061', '7062'],
table: 'filter',
},
args: ['-t', :filter, '-s', '1.1.1.1/32', '-d', '1.1.1.1/32', '-p', :tcp, '-m', 'multiport', '--sports', '7061,7062', '-m', 'multiport', '--dports', '7061,7062', '-j', 'ACCEPT', '-m', 'comment', '--comment', '000 allow foo'], # rubocop:disable Metrics/LineLength
Expand All @@ -719,7 +719,7 @@
name: '700 allow bar',
proto: 'udp',
source: '1.1.1.1',
sport: %w[7061 7062],
sport: ['7061', '7062'],
table: 'filter',
},
args: ['-t', :filter, '-s', '1.1.1.1/32', '-d', '2.10.13.0/24', '-p', :udp, '-m', 'multiport', '--sports', '7061,7062', '-m', 'multiport', '--dports', '7061', '-j', 'my_custom_chain', '-m', 'comment', '--comment', '700 allow bar'], # rubocop:disable Metrics/LineLength
Expand Down Expand Up @@ -863,15 +863,15 @@
params: {
name: '100 states_set_from_array',
table: 'filter',
state: %w[ESTABLISHED INVALID],
state: ['ESTABLISHED', 'INVALID'],
},
args: ['-t', :filter, '-p', :tcp, '-m', 'state', '--state', 'ESTABLISHED,INVALID', '-m', 'comment', '--comment', '100 states_set_from_array'],
},
'ctstates_set_from_array' => {
params: {
name: '100 ctstates_set_from_array',
table: 'filter',
ctstate: %w[ESTABLISHED INVALID],
ctstate: ['ESTABLISHED', 'INVALID'],
},
args: ['-t', :filter, '-p', :tcp, '-m', 'conntrack', '--ctstate', 'ESTABLISHED,INVALID', '-m', 'comment', '--comment', '100 ctstates_set_from_array'],
},
Expand Down
22 changes: 21 additions & 1 deletion spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
require 'puppetlabs_spec_helper/module_spec_helper'
require 'rspec-puppet-facts'

begin
require 'spec_helper_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_local.rb'))
rescue LoadError => loaderror
warn "Could not require spec_helper_local: #{loaderror.message}"
end

include RspecPuppetFacts

default_facts = {
Expand All @@ -20,5 +27,18 @@

RSpec.configure do |c|
c.default_facts = default_facts
c.before :each do
# set to strictest setting for testing
# by default Puppet runs at warning level
Puppet.settings[:strict] = :warning
end
end
require 'spec_helper_local'

def ensure_module_defined(module_name)
module_name.split('::').reduce(Object) do |last_module, next_module|
last_module.const_set(next_module, Module.new) unless last_module.const_defined?(next_module)
last_module.const_get(next_module)
end
end

# 'spec_overrides' from sync.yml will appear below this line
7 changes: 5 additions & 2 deletions spec/spec_helper_acceptance.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
require 'beaker-pe'
require 'beaker-puppet'
require 'beaker-rspec'
require 'beaker/puppet_install_helper'
require 'beaker/module_install_helper'

def iptables_flush_all_tables
%w[filter nat mangle raw].each do |t|
['filter', 'nat', 'mangle', 'raw'].each do |t|
expect(shell("iptables -t #{t} -F").stderr).to eq('')
end
end

def ip6tables_flush_all_tables
%w[filter mangle].each do |t|
['filter', 'mangle'].each do |t|
expect(shell("ip6tables -t #{t} -F").stderr).to eq('')
end
end
Expand All @@ -23,6 +25,7 @@ def do_catch_changes
end

run_puppet_install_helper
configure_type_defaults_on(hosts)
install_module_on(hosts)
install_module_dependencies_on(hosts)

Expand Down
40 changes: 0 additions & 40 deletions spec/unit/classes/firewall_linux_debian_spec.rb
Original file line number Diff line number Diff line change
@@ -1,46 +1,6 @@
require 'spec_helper'

describe 'firewall::linux::debian', type: :class do
context 'with Debian 7' do
let(:facts) do
{
osfamily: 'Debian',
operatingsystem: 'Debian',
operatingsystemrelease: '7.0',
}
end

it {
is_expected.to contain_package('iptables-persistent').with(
ensure: 'present',
)
}
it {
is_expected.to contain_service('iptables-persistent').with(
ensure: nil,
enable: 'true',
require: 'Package[iptables-persistent]',
)
}
end

context 'with deb7 enable => false' do
let(:facts) do
{
osfamily: 'Debian',
operatingsystem: 'Debian',
operatingsystemrelease: '7.0',
}
end
let(:params) { { enable: 'false' } }

it {
is_expected.to contain_service('iptables-persistent').with(
enable: 'false',
)
}
end

context 'with Debian 8' do
let(:facts) do
{
Expand Down
4 changes: 2 additions & 2 deletions spec/unit/classes/firewall_linux_redhat_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@
end

describe 'firewall::linux::redhat', type: :class do
%w[RedHat CentOS Fedora].each do |os|
['RedHat', 'CentOS', 'Fedora'].each do |os|
oldreleases = ((os == 'Fedora') ? ['14'] : ['6.5'])
newreleases = ((os == 'Fedora') ? %w[15 Rawhide] : ['7.0.1406'])
newreleases = ((os == 'Fedora') ? ['15', 'Rawhide'] : ['7.0.1406'])

oldreleases.each do |osrel|
context "os #{os} and osrel #{osrel}" do
Expand Down
8 changes: 4 additions & 4 deletions spec/unit/classes/firewall_linux_spec.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
require 'spec_helper'

describe 'firewall::linux', type: :class do
%w[RedHat CentOS Fedora].each do |os|
['RedHat', 'CentOS'].each do |os|
context "Redhat Like: operatingsystem => #{os}" do
releases = ((os == 'Fedora') ? %w[14 15 Rawhide] : %w[6 7])
releases = ['6', '7']
releases.each do |osrel|
context "operatingsystemrelease => #{osrel}" do
let(:facts) do
Expand All @@ -24,9 +24,9 @@
end
end

%w[Debian Ubuntu].each do |os|
['Debian', 'Ubuntu'].each do |os|
context "Debian Like: operatingsystem => #{os}" do
releases = ((os == 'Debian') ? %w[6 7 8] : ['10.04', '12.04', '14.04'])
releases = ((os == 'Debian') ? ['8'] : ['14.04'])
releases.each do |osrel|
let(:facts) do
{
Expand Down
8 changes: 1 addition & 7 deletions spec/unit/facter/iptables_persistent_version_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,9 @@
let(:dpkg_cmd) { "dpkg-query -Wf '${Version}' iptables-persistent 2>/dev/null" }

{
'Debian' => '0.0.20090701',
'Ubuntu' => '0.5.3ubuntu2',
}.each do |os, ver|

if os == 'Debian'
os_release = '7.0'
elsif os == 'Ubuntu'
os_release = '14.04'
end
os_release = '14.04'

describe "#{os} package installed" do
before(:each) do
Expand Down
32 changes: 31 additions & 1 deletion spec/unit/puppet/provider/iptables_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@
end

resource_types = [:chain, :source, :destination, :proto, :dport, :sport, :action]
rule_values = ['INPUT', '1.1.1.1/32', '1.1.1.1/32', 'tcp', %w[7061 7062], %w[7061 7062], 'accept']
rule_values = ['INPUT', '1.1.1.1/32', '1.1.1.1/32', 'tcp', ['7061', '7062'], ['7061', '7062'], 'accept']
it 'parsed the rule arguments correctly' do
resource_types.each_with_index do |type, index|
expect(resource[type]).to eq(rule_values[index])
Expand Down Expand Up @@ -435,4 +435,34 @@
end
end
end

describe 'when deleting ipv6 resources' do
let(:sample_rule) do
'-A INPUT -i lo -m comment --comment "001 accept all to lo interface v6" -j ACCEPT'
end

let(:bare_sample_rule) do
'-A INPUT -i lo -m comment --comment 001 accept all to lo interface v6 -j ACCEPT'
end

let(:resource) { provider6.rule_to_hash(sample_rule, 'filter', 0) }
let(:instance) { provider6.new(resource) }

it 'resource[:line] looks like the original rule' do
resource[:line] == sample_rule
end

it 'delete_args is an array' do
expect(instance.delete_args.class).to eq(Array)
end

it 'attempts to match ipv6 rule' do
expect(instance.delete_args).to eq(['-t', 'filter', '-D', 'INPUT', '-i', 'lo', '-m', 'comment', '--comment', '001 accept all to lo interface v6', '-j', 'ACCEPT', '-p', 'all'])
end

it 'delete_args is the same as the rule string when joined' do
expect(instance.delete_args.join(' ')).to eq(bare_sample_rule.gsub(%r{\-A},
'-t filter -D') + ' -p all')
end
end
end
18 changes: 9 additions & 9 deletions spec/unit/puppet/type/firewall_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,14 @@
expect(res.parameters[:jump]).to be nil
end

%w[QUEUE RETURN DNAT SNAT LOG NFLOG MASQUERADE REDIRECT MARK].each do |jump|
['QUEUE', 'RETURN', 'DNAT', 'SNAT', 'LOG', 'NFLOG', 'MASQUERADE', 'REDIRECT', 'MARK'].each do |jump|
it "should accept jump value #{jump}" do
resource[:jump] = jump
expect(resource[:jump]).to eql jump
end
end

%w[ACCEPT DROP REJECT].each do |jump|
['ACCEPT', 'DROP', 'REJECT'].each do |jump|
it "should now fail when value #{jump}" do
expect(-> { resource[:jump] = jump }).to raise_error(Puppet::Error)
end
Expand Down Expand Up @@ -145,8 +145,8 @@
end

it "should accept a #{port} as an array" do
resource[port] = %w[22 23]
expect(resource[port]).to eql %w[22 23]
resource[port] = ['22', '23']
expect(resource[port]).to eql ['22', '23']
end

it "should accept a #{port} as a number" do
Expand Down Expand Up @@ -412,7 +412,7 @@
end

describe ':recent' do
%w[set update rcheck remove].each do |recent|
['set', 'update', 'rcheck', 'remove'].each do |recent|
it "should accept recent value #{recent}" do
resource[:recent] = recent
expect(resource[:recent]).to eql "--#{recent}"
Expand All @@ -433,15 +433,15 @@
expect(resource[:uid]).to eql 'root'
end
it 'allows me to set uid as an array, and silently hide my error' do
resource[:uid] = %w[root bobby]
resource[:uid] = ['root', 'bobby']
expect(resource[:uid]).to eql 'root'
end
it 'allows me to set gid' do
resource[:gid] = 'root'
expect(resource[:gid]).to eql 'root'
end
it 'allows me to set gid as an array, and silently hide my error' do
resource[:gid] = %w[root bobby]
resource[:gid] = ['root', 'bobby']
expect(resource[:gid]).to eql 'root'
end
end
Expand Down Expand Up @@ -577,7 +577,7 @@
end

# test where autorequire is still needed (table != filter)
%w[INPUT OUTPUT FORWARD].each do |test_chain|
['INPUT', 'OUTPUT', 'FORWARD'].each do |test_chain|
it "should autorequire fwchain #{test_chain} when table is mangle and provider is undefined" do
resource[param] = test_chain
resource[:table] = :mangle
Expand Down Expand Up @@ -608,7 +608,7 @@
end

# test of case where autorequire should not happen
%w[INPUT OUTPUT FORWARD].each do |test_chain|
['INPUT', 'OUTPUT', 'FORWARD'].each do |test_chain|
it "should not autorequire fwchain #{test_chain} when table and provider are undefined" do
resource[param] = test_chain
expect(resource[:table]).to be :filter
Expand Down
15 changes: 7 additions & 8 deletions spec/unit/puppet/type/firewallchain_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@
end

describe ':name' do
{ 'nat' => %w[PREROUTING POSTROUTING INPUT OUTPUT],
'mangle' => %w[PREROUTING POSTROUTING INPUT FORWARD OUTPUT],
'filter' => %w[INPUT OUTPUT FORWARD],
'raw' => %w[PREROUTING OUTPUT],
{ 'nat' => ['PREROUTING', 'POSTROUTING', 'INPUT', 'OUTPUT'],
'mangle' => ['PREROUTING', 'POSTROUTING', 'INPUT', 'FORWARD', 'OUTPUT'],
'filter' => ['INPUT', 'OUTPUT', 'FORWARD'],
'raw' => ['PREROUTING', 'OUTPUT'],
'broute' => ['BROUTING'],
'security' => %w[INPUT OUTPUT FORWARD] }.each_pair do |table, allowedinternalchains|
%w[IPv4 IPv6 ethernet].each do |protocol|
'security' => ['INPUT', 'OUTPUT', 'FORWARD'] }.each_pair do |table, allowedinternalchains|
['IPv4', 'IPv6', 'ethernet'].each do |protocol|
['test', '$5()*&%\'"^$09):'].each do |chainname|
name = "#{chainname}:#{table}:#{protocol}"
if table == 'nat' && protocol == 'IPv6'
Expand All @@ -58,7 +58,7 @@
end
end

%w[PREROUTING POSTROUTING BROUTING INPUT FORWARD OUTPUT].each do |internalchain|
['PREROUTING', 'POSTROUTING', 'BROUTING', 'INPUT', 'FORWARD', 'OUTPUT'].each do |internalchain|
name = internalchain + ':' + table + ':'
name += if internalchain == 'BROUTING'
'ethernet'
Expand Down Expand Up @@ -145,7 +145,6 @@
end

describe 'purge iptables rules' do
# rubocop:disable Layout/IndentHeredoc
before(:each) do
stub_return = <<PUPPETCODE
# Completed on Sun Jan 5 19:30:21 2014
Expand Down
16 changes: 8 additions & 8 deletions spec/unit/puppet/util/firewall_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
describe 'proto unsupported' do
subject(:host) { resource }

%w[inet5 inet8 foo].each do |proto|
['inet5', 'inet8', 'foo'].each do |proto|
it "should reject invalid proto #{proto}" do
expect { host.icmp_name_to_number('echo-reply', proto) }
.to raise_error(ArgumentError, "unsupported protocol family '#{proto}'")
Expand Down Expand Up @@ -133,7 +133,7 @@
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return('RedHat')
allow(Facter.fact(:operatingsystemrelease)).to receive(:value).and_return('6')

allow(host).to receive(:execute).with(%w[/sbin/service iptables save])
allow(host).to receive(:execute).with(['/sbin/service', 'iptables', 'save'])
host.persist_iptables(proto)
end

Expand All @@ -142,7 +142,7 @@
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return('RedHat')
allow(Facter.fact(:operatingsystemrelease)).to receive(:value).and_return('7')

allow(host).to receive(:execute).with(%w[/usr/libexec/iptables/iptables.init save])
allow(host).to receive(:execute).with(['/usr/libexec/iptables/iptables.init', 'save'])
host.persist_iptables(proto)
end

Expand All @@ -151,23 +151,23 @@
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return('Fedora')
allow(Facter.fact(:operatingsystemrelease)).to receive(:value).and_return('15')

allow(host).to receive(:execute).with(%w[/usr/libexec/iptables/iptables.init save])
allow(host).to receive(:execute).with(['/usr/libexec/iptables/iptables.init', 'save'])
host.persist_iptables(proto)
end

it 'is expected to exec for CentOS 6 identified from operatingsystem and operatingsystemrelease' do
allow(Facter.fact(:osfamily)).to receive(:value).and_return(nil)
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return('CentOS')
allow(Facter.fact(:operatingsystemrelease)).to receive(:value).and_return('6.5')
allow(host).to receive(:execute).with(%w[/sbin/service iptables save])
allow(host).to receive(:execute).with(['/sbin/service', 'iptables', 'save'])
host.persist_iptables(proto)
end

it 'is expected to exec for CentOS 7 identified from operatingsystem and operatingsystemrelease' do
allow(Facter.fact(:osfamily)).to receive(:value).and_return(nil)
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return('CentOS')
allow(Facter.fact(:operatingsystemrelease)).to receive(:value).and_return('7.0.1406')
allow(host).to receive(:execute).with(%w[/usr/libexec/iptables/iptables.init save])
allow(host).to receive(:execute).with(['/usr/libexec/iptables/iptables.init', 'save'])
host.persist_iptables(proto)
end

Expand All @@ -182,7 +182,7 @@
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return('RedHat')
allow(Facter.fact(:operatingsystemrelease)).to receive(:value).and_return('6')

allow(host).to receive(:execute).with(%w[/sbin/service iptables save]).and_raise(Puppet::ExecutionFailure, 'some error')
allow(host).to receive(:execute).with(['/sbin/service', 'iptables', 'save']).and_raise(Puppet::ExecutionFailure, 'some error')
allow(host).to receive(:warning).with('Unable to persist firewall rules: some error')
host.persist_iptables(proto)
end
Expand All @@ -195,7 +195,7 @@
allow(Facter.fact(:osfamily)).to receive(:value).and_return(nil)
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return('Ubuntu')
allow(Facter.fact(:iptables_persistent_version)).to receive(:value).and_return('0.5.3ubuntu2')
allow(host).to receive(:execute).with(%w[/usr/sbin/service iptables-persistent save])
allow(host).to receive(:execute).with(['/usr/sbin/service', 'iptables-persistent', 'save'])
host.persist_iptables(proto)
end

Expand Down