145 changes: 82 additions & 63 deletions REFERENCE.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion lib/facter/ip6tables_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Facter.add(:ip6tables_version) do
confine kernel: :Linux
setcode do
version = Facter::Util::Resolution.exec('ip6tables --version')
version = Facter::Core::Execution.execute('ip6tables --version')
if version
version.match(%r{\d+\.\d+\.\d+}).to_s
else
Expand Down
12 changes: 2 additions & 10 deletions lib/facter/iptables_persistent_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,8 @@
setcode do
# Throw away STDERR because dpkg >= 1.16.7 will make some noise if the
# package isn't currently installed.
os = Facter.value(:operatingsystem)
os_release = Facter.value(:operatingsystemrelease)
cmd = if (os == 'Debian' && (Puppet::Util::Package.versioncmp(os_release, '8.0') >= 0)) ||
(os == 'Ubuntu' && (Puppet::Util::Package.versioncmp(os_release, '14.10') >= 0)) ||
(os == 'Debian' && (Puppet::Util::Package.versioncmp(os_release, 'unstable') >= 0))
"dpkg-query -Wf '${Version}' netfilter-persistent 2>/dev/null"
else
"dpkg-query -Wf '${Version}' iptables-persistent 2>/dev/null"
end
version = Facter::Util::Resolution.exec(cmd)
cmd = "dpkg-query -Wf '${Version}' netfilter-persistent 2>/dev/null"
version = Facter::Core::Execution.execute(cmd)

if version.nil? || !version.match(%r{\d+\.\d+})
nil
Expand Down
2 changes: 1 addition & 1 deletion lib/facter/iptables_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Facter.add(:iptables_version) do
confine kernel: :Linux
setcode do
version = Facter::Util::Resolution.exec('iptables --version')
version = Facter::Core::Execution.execute('iptables --version')
if version
version.match(%r{\d+\.\d+\.\d+}).to_s
else
Expand Down
15 changes: 15 additions & 0 deletions lib/puppet/provider/firewall/iptables.rb
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,17 @@ def self.rule_to_hash(line, table, counter)
(\s--tunnel-src\s\S+)?
(\s--next)?}x,
'--pol "ipsec\1\2\3\4\5\6\7\8" ')

# rpfilter also takes multiple parameters; use quote trick again
rpfilter_opts = values.scan(%r{-m\srpfilter(\s(--loose)|\s(--validmark)|\s(--accept-local)|\s(--invert))+})
if rpfilter_opts && rpfilter_opts.length == 1 && rpfilter_opts[0]
rpfilter_opts = rpfilter_opts[0][1..-1].reject { |x| x.nil? }
values = values.sub(
%r{-m\srpfilter(\s(--loose)|\s(--validmark)|\s(--accept-local)|\s(--invert))+},
"-m rpfilter \"#{rpfilter_opts.join(' ')}\"",
)
end

# on some iptables versions, --connlimit-saddr switch is added after the rule is applied
values = values.gsub(%r{--connlimit-saddr}, '')

Expand Down Expand Up @@ -632,6 +643,8 @@ def self.rule_to_hash(line, table, counter)
hash[prop] = hash[prop].split(';') unless hash[prop].nil?
end

hash[:rpfilter] = hash[:rpfilter].split(' ') unless hash[:rpfilter].nil?

## clean up DSCP class to HEX mappings
valid_dscp_classes = {
'0x0a' => 'af11',
Expand Down Expand Up @@ -918,6 +931,8 @@ def general_args
one, two = resource_value.split(' ')
args << one
args << two
elsif res == :rpfilter
args << resource_value
elsif resource_value.is_a?(Array)
args << resource_value.join(',')
elsif !resource_value.nil?
Expand Down
43 changes: 22 additions & 21 deletions lib/puppet/type/firewall.rb
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,17 @@
end
end

newproperty(:proto) do
desc <<-PUPPETCODE
The specific protocol to match for this rule.
PUPPETCODE

newvalues(*[:ip, :tcp, :udp, :icmp, :"ipv6-icmp", :esp, :ah, :vrrp, :carp, :igmp, :ipencap, :ipv4, :ipv6, :ospf, :gre, :cbt, :sctp, :pim, :all].map { |proto|
[proto, "! #{proto}".to_sym]
}.flatten)
defaultto 'tcp'
end

newproperty(:sport, array_matching: :all) do
desc <<-PUPPETCODE
The source port to match for this filter (if the protocol supports
Expand All @@ -399,7 +410,7 @@
PUPPETCODE

munge do |value|
@resource.string_to_port(value, :proto)
@resource.string_to_port(value, @resource[:proto])
end

def to_s?(value)
Expand Down Expand Up @@ -429,7 +440,7 @@ def should_to_s(value)
PUPPETCODE

munge do |value|
@resource.string_to_port(value, :proto)
@resource.string_to_port(value, @resource[:proto])
end

def to_s?(value)
Expand Down Expand Up @@ -465,7 +476,7 @@ def should_to_s(value)
end

munge do |value|
@resource.string_to_port(value, :proto)
@resource.string_to_port(value, @resource[:proto])
end

def to_s?(value)
Expand Down Expand Up @@ -568,17 +579,6 @@ def should_to_s(value)
}.flatten)
end

newproperty(:proto) do
desc <<-PUPPETCODE
The specific protocol to match for this rule.
PUPPETCODE

newvalues(*[:ip, :tcp, :udp, :icmp, :"ipv6-icmp", :esp, :ah, :vrrp, :carp, :igmp, :ipencap, :ipv4, :ipv6, :ospf, :gre, :cbt, :sctp, :pim, :all].map { |proto|
[proto, "! #{proto}".to_sym]
}.flatten)
defaultto 'tcp'
end

# tcp-specific
newproperty(:mss) do
desc <<-PUPPETCODE
Expand Down Expand Up @@ -1705,7 +1705,7 @@ def insync?(is)
newvalues(:true, :false)
end

newproperty(:rpfilter, required_features: :rpfilter) do
newproperty(:rpfilter, required_features: :rpfilter, array_matching: :all) do
desc <<-PUPPETCODE
Enable the rpfilter module.
PUPPETCODE
Expand All @@ -1714,6 +1714,10 @@ def insync?(is)
munge do |value|
_value = '--' + value
end

def insync?(is)
is.to_set == should.to_set
end
end

newproperty(:socket, required_features: :socket) do
Expand Down Expand Up @@ -2342,12 +2346,9 @@ def should_to_s(value)
end
end

# autobefore is only provided since puppet 4.0
if Puppet::Util::Package.versioncmp(Puppet.version, '4.0') >= 0
# On RHEL 7 this needs to be threaded correctly to manage SE Linux permissions after persisting the rules
autobefore(:file) do
['/etc/sysconfig/iptables', '/etc/sysconfig/ip6tables']
end
# On RHEL 7 this needs to be threaded correctly to manage SE Linux permissions after persisting the rules
autobefore(:file) do
['/etc/sysconfig/iptables', '/etc/sysconfig/ip6tables']
end

validate do
Expand Down
39 changes: 9 additions & 30 deletions manifests/linux/debian.pp
Original file line number Diff line number Diff line change
Expand Up @@ -26,38 +26,17 @@
$package_ensure = $firewall::params::package_ensure,
) inherits ::firewall::params {
if $package_name {
#Fixes hang while installing iptables-persistent on debian 8
exec { 'iptables-persistent-debconf':
command => "/bin/echo \"${package_name} ${package_name}/autosave_v4 boolean false\" |
/usr/bin/debconf-set-selections && /bin/echo \"${package_name} ${package_name}/autosave_v6 boolean false\" |
/usr/bin/debconf-set-selections",

refreshonly => true,
}
ensure_packages([$package_name],{
ensure => $package_ensure,
require => Exec['iptables-persistent-debconf']
ensure_packages([$package_name], {
ensure => $package_ensure
})
}

if($::operatingsystemrelease =~ /^6\./ and $enable == true and $::iptables_persistent_version
and versioncmp($::iptables_persistent_version, '0.5.0') < 0) {
# This fixes a bug in the iptables-persistent LSB headers in 6.x, without it
# we lose idempotency
exec { 'iptables-persistent-enable':
logoutput => on_failure,
command => '/usr/sbin/update-rc.d iptables-persistent enable',
unless => '/usr/bin/test -f /etc/rcS.d/S*iptables-persistent',
require => Package[$package_name],
}
} else {
# This isn't a real service/daemon. The start action loads rules, so just
# needs to be called on system boot.
service { $service_name:
ensure => undef,
enable => $enable,
hasstatus => true,
require => Package[$package_name],
}
# This isn't a real service/daemon. The start action loads rules, so just
# needs to be called on system boot.
service { $service_name:
ensure => undef,
enable => $enable,
hasstatus => true,
require => Package[$package_name],
}
}
23 changes: 5 additions & 18 deletions manifests/linux/redhat.pp
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@
# RHEL 7 / CentOS 7 and later and Fedora 15 and later require the iptables-services
# package, which provides the /usr/libexec/iptables/iptables.init used by
# lib/puppet/util/firewall.rb.
if ($::operatingsystem != 'Amazon')
and (($::operatingsystem != 'Fedora' and versioncmp($::operatingsystemrelease, '7.0') >= 0)
or ($::operatingsystem == 'Fedora' and versioncmp($::operatingsystemrelease, '15') >= 0)) {
if ($::operatingsystem != 'Amazon') {
if $firewalld_manage {
service { 'firewalld':
ensure => stopped,
Expand All @@ -74,11 +72,12 @@
)
}

if ($::operatingsystem != 'Amazon')
and (($::operatingsystem != 'Fedora' and versioncmp($::operatingsystemrelease, '7.0') >= 0)
or ($::operatingsystem == 'Fedora' and versioncmp($::operatingsystemrelease, '15') >= 0)) {
if ($::operatingsystem != 'Amazon') {
if $ensure == 'running' {
$running_command = ['/usr/bin/systemctl', 'daemon-reload']

exec { '/usr/bin/systemctl daemon-reload':
command => $running_command,
require => Package[$package_name],
before => Service[$service_name, $service_name_v6],
subscribe => Package[$package_name],
Expand Down Expand Up @@ -134,13 +133,6 @@
}
}

# Before puppet 4, the autobefore on the firewall type does not work - therefore
# we need to keep this workaround here
if versioncmp($::puppetversion, '4.0') <= 0 {
File<| title == "/etc/sysconfig/${service_name}" |> -> Service<| title == $service_name |>
File<| title == "/etc/sysconfig/${service_name_v6}" |> -> Service<| title == $service_name_v6 |>
}

# Redhat 7 selinux user context for /etc/sysconfig/iptables is set to system_u
# Redhat 7 selinux type context for /etc/sysconfig/iptables is set to system_conf_t
case $::selinux {
Expand All @@ -149,11 +141,6 @@
case $::operatingsystem {
'CentOS': {
case $::operatingsystemrelease {
/^5\..*/: {
$seluser = 'system_u'
$seltype = 'etc_t'
}

/^6\..*/: {
$seluser = 'unconfined_u'
$seltype = 'system_conf_t'
Expand Down
3 changes: 0 additions & 3 deletions manifests/params.pp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@
if versioncmp($::operatingsystemrelease, '34') >= 0 {
$package_name = 'iptables-services'
$iptables_name = 'iptables-compat'
} elsif versioncmp($::operatingsystemrelease, '15') >= 0 {
$package_name = 'iptables-services'
$iptables_name = 'iptables'
} else {
$iptables_name = 'iptables'
$package_name = undef
Expand Down
10 changes: 3 additions & 7 deletions metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "puppetlabs-firewall",
"version": "3.6.0",
"version": "4.0.0",
"author": "puppetlabs",
"summary": "Manages Firewalls such as iptables",
"license": "Apache-2.0",
Expand All @@ -17,7 +17,6 @@
{
"operatingsystem": "RedHat",
"operatingsystemrelease": [
"6",
"7",
"8",
"9"
Expand All @@ -33,14 +32,12 @@
{
"operatingsystem": "OracleLinux",
"operatingsystemrelease": [
"6",
"7"
]
},
{
"operatingsystem": "Scientific",
"operatingsystemrelease": [
"6",
"7"
]
},
Expand All @@ -54,7 +51,6 @@
{
"operatingsystem": "Debian",
"operatingsystemrelease": [
"9",
"10",
"11"
]
Expand Down Expand Up @@ -87,6 +83,6 @@
}
],
"template-url": "https://github.com/puppetlabs/pdk-templates.git#main",
"template-ref": "heads/main-0-g806810b",
"pdk-version": "2.4.0"
"template-ref": "tags/2.6.0-0-gd0490b9",
"pdk-version": "2.5.0"
}
12 changes: 12 additions & 0 deletions spec/acceptance/firewall_attributes_happy_path_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,12 @@ class { '::firewall': }
physdev_is_bridged => true,
}
firewall { '900 - set rpfilter':
table => 'raw',
chain => 'PREROUTING',
action => 'accept',
rpfilter => [ 'invert', 'validmark', 'loose', 'accept-local' ],
}
firewall { '901 - set rpfilter':
table => 'raw',
chain => 'PREROUTING',
action => 'accept',
Expand Down Expand Up @@ -421,6 +427,12 @@ class { '::firewall': }
it 'toports is set' do
expect(result.stdout).to match(%r{-A PREROUTING -p icmp -m comment --comment "574 - toports" -j REDIRECT --to-ports 2222})
end
it 'rpfilter is set' do
expect(result.stdout).to match(%r{-A PREROUTING -p tcp -m rpfilter --loose --validmark --accept-local --invert -m comment --comment "900 - set rpfilter" -j ACCEPT})
end
it 'single rpfilter is set' do
expect(result.stdout).to match(%r{-A PREROUTING -p tcp -m rpfilter --invert -m comment --comment "901 - set rpfilter" -j ACCEPT})
end
it 'limit is set' do
expect(result.stdout).to match(%r{-A INPUT -p tcp -m multiport --dports 572 -m limit --limit 500\/sec -m comment --comment "572 - limit" -j ACCEPT})
end
Expand Down
56 changes: 8 additions & 48 deletions spec/unit/classes/firewall_linux_debian_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,12 @@
require 'spec_helper'

describe 'firewall::linux::debian', type: :class do
context 'with Debian 8' do
let(:facts) do
{
osfamily: 'Debian',
operatingsystem: 'Debian',
operatingsystemrelease: 'jessie/sid',
}
end

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

context 'with deb8 enable => false' do
let(:facts) do
{
osfamily: 'Debian',
operatingsystem: 'Debian',
operatingsystemrelease: 'jessie/sid',
}
end
let(:params) { { enable: 'false' } }

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

context 'with Debian 8, alt operatingsystem' do
context 'with Debian 10' do
let(:facts) do
{
osfamily: 'Debian',
operatingsystem: 'Debian',
operatingsystemrelease: '8.0',
operatingsystemrelease: '10.0',
}
end

Expand All @@ -66,12 +26,12 @@
}
end

context 'with deb8, alt operatingsystem, enable => false' do
context 'with Debian 10, enable => false' do
let(:facts) do
{
osfamily: 'Debian',
operatingsystem: 'Debian',
operatingsystemrelease: '8.0',
operatingsystemrelease: '10',
}
end
let(:params) { { enable: 'false' } }
Expand All @@ -83,12 +43,12 @@
}
end

context 'with Debian 10' do
context 'with Debian 11' do
let(:facts) do
{
osfamily: 'Debian',
operatingsystem: 'Debian',
operatingsystemrelease: '10.0',
operatingsystemrelease: '11.0',
}
end

Expand All @@ -106,12 +66,12 @@
}
end

context 'with Debian 10, enable => false' do
context 'with Debian 11, enable => false' do
let(:facts) do
{
osfamily: 'Debian',
operatingsystem: 'Debian',
operatingsystemrelease: '10',
operatingsystemrelease: '11',
}
end
let(:params) { { enable: 'false' } }
Expand Down
28 changes: 2 additions & 26 deletions spec/unit/classes/firewall_linux_redhat_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,34 +35,10 @@

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

oldreleases.each do |osrel|
context "os #{os} and osrel #{osrel}" do
let(:facts) do
{
operatingsystem: os,
operatingsystemrelease: osrel,
osfamily: 'RedHat',
selinux: false,
puppetversion: Puppet.version,
}
end

it { is_expected.not_to contain_service('firewalld') }
it { is_expected.not_to contain_package('iptables-services') }
it {
is_expected.to contain_file('/etc/sysconfig/iptables')
is_expected.to contain_file('/etc/sysconfig/ip6tables')
}

it_behaves_like 'ensures iptables service'
end
end

newreleases.each do |osrel|
releases.each do |osrel|
context "os #{os} and osrel #{osrel}" do
let(:facts) do
{
Expand Down
4 changes: 2 additions & 2 deletions spec/unit/classes/firewall_linux_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
describe 'firewall::linux', type: :class do
['RedHat', 'CentOS'].each do |os|
context "Redhat Like: operatingsystem => #{os}" do
releases = ['6', '7']
releases = ['6', '7', '8']
releases.each do |osrel|
context "operatingsystemrelease => #{osrel}" do
let(:facts) do
Expand All @@ -28,7 +28,7 @@

['Debian', 'Ubuntu'].each do |os|
context "Debian Like: operatingsystem => #{os}" do
releases = ((os == 'Debian') ? ['10'] : ['20.04'])
releases = ((os == 'Debian') ? ['10', '11'] : ['20.04', '22.04'])
releases.each do |osrel|
let(:facts) do
{
Expand Down
16 changes: 8 additions & 8 deletions spec/unit/facter/iptables_persistent_version_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
before(:each) do
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return(os)
allow(Facter.fact(:operatingsystemrelease)).to receive(:value).and_return(os_release)
allow(Facter::Util::Resolution).to receive(:exec).with(dpkg_cmd)
.and_return(ver)
allow(Facter::Core::Execution).to receive(:execute).with(dpkg_cmd)
.and_return(ver)
end
it { expect(Facter.fact(:iptables_persistent_version).value).to eql ver }
end
Expand All @@ -28,8 +28,8 @@
before(:each) do
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return('Ubuntu')
allow(Facter.fact(:operatingsystemrelease)).to receive(:value).and_return('20.04')
allow(Facter::Util::Resolution).to receive(:exec).with(dpkg_cmd)
.and_return(nil)
allow(Facter::Core::Execution).to receive(:execute).with(dpkg_cmd)
.and_return(nil)
end
it { expect(Facter.fact(:iptables_persistent_version).value).to be_nil }
end
Expand Down Expand Up @@ -62,8 +62,8 @@
before(:each) do
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return(os)
allow(Facter.fact(:operatingsystemrelease)).to receive(:value).and_return(os_release)
allow(Facter::Util::Resolution).to receive(:exec).with(dpkg_cmd)
.and_return(ver)
allow(Facter::Core::Execution).to receive(:execute).with(dpkg_cmd)
.and_return(ver)
end
it { expect(Facter.fact(:iptables_persistent_version).value).to eql ver }
end
Expand All @@ -74,8 +74,8 @@
before(:each) do
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return('Ubuntu')
allow(Facter.fact(:operatingsystemrelease)).to receive(:value).and_return(os_release)
allow(Facter::Util::Resolution).to receive(:exec).with(dpkg_cmd)
.and_return(nil)
allow(Facter::Core::Execution).to receive(:execute).with(dpkg_cmd)
.and_return(nil)
end
it { expect(Facter.fact(:iptables_persistent_version).value).to be_nil }
end
Expand Down
6 changes: 3 additions & 3 deletions spec/unit/facter/iptables_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@

describe 'iptables_version' do
it {
allow(Facter::Util::Resolution).to receive(:exec).with('iptables --version')
.and_return('iptables v1.4.7')
allow(Facter::Core::Execution).to receive(:execute).with('iptables --version')
.and_return('iptables v1.4.7')
expect(Facter.fact(:iptables_version).value).to eql '1.4.7'
}
end

describe 'ip6tables_version' do
before(:each) do
allow(Facter::Util::Resolution).to receive(:exec)
allow(Facter::Core::Execution).to receive(:execute)
.with('ip6tables --version').and_return('ip6tables v1.4.7')
end
it { expect(Facter.fact(:ip6tables_version).value).to eql '1.4.7' }
Expand Down
7 changes: 2 additions & 5 deletions spec/unit/puppet/provider/ip6tables_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@
# frozen_string_literal: true

require 'spec_helper'
if Puppet::Util::Package.versioncmp(Puppet.version, '3.4.0') < 0
require 'puppet/provider/confine/exists'
else
require 'puppet/confine/exists'
end
require 'puppet/confine/exists'

provider_class = Puppet::Type.type(:firewall).provider(:ip6tables)
describe 'ip6tables' do
let(:params) { { name: '000 test foo', action: 'accept' } }
Expand Down
16 changes: 3 additions & 13 deletions spec/unit/puppet/provider/iptables_chain_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,12 @@
# frozen_string_literal: true

require 'spec_helper'
if Puppet::Util::Package.versioncmp(Puppet.version, '3.4.0') < 0
require 'puppet/provider/confine/exists'
else
require 'puppet/confine/exists'
end
require 'puppet/confine/exists'

describe 'iptables chain' do
describe 'iptables chain provider detection' do
if Puppet::Util::Package.versioncmp(Puppet.version, '3.4.0') < 0
let(:exists) do
Puppet::Provider::Confine::Exists
end
else
let(:exists) do
Puppet::Confine::Exists
end
let(:exists) do
Puppet::Confine::Exists
end

before :each do
Expand Down
20 changes: 5 additions & 15 deletions spec/unit/puppet/provider/iptables_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,11 @@
# frozen_string_literal: true

require 'spec_helper'
if Puppet::Util::Package.versioncmp(Puppet.version, '3.4.0') < 0
require 'puppet/provider/confine/exists'
else
require 'puppet/confine/exists'
end
require 'puppet/confine/exists'

describe 'iptables provider detection' do # rubocop:disable RSpec/MultipleDescribes
if Puppet::Util::Package.versioncmp(Puppet.version, '3.4.0') < 0
let(:exists) do
Puppet::Provider::Confine::Exists
end
else
let(:exists) do
Puppet::Confine::Exists
end
let(:exists) do
Puppet::Confine::Exists
end

before :each do
Expand Down Expand Up @@ -331,14 +321,14 @@
chain: 'nova-compute-FORWARD',
source: '0.0.0.0/32',
destination: '255.255.255.255/32',
sport: ['! 78', '79', 'http'],
sport: ['! 78', '79', 'talk'],
dport: ['77', '! 76'],
proto: 'udp')
end
let(:instance) { provider.new(resource) }

it 'fails when not all array items are inverted' do
expect { instance.insert }.to raise_error RuntimeError, %r{but '79', '80' are not prefixed}
expect { instance.insert }.to raise_error RuntimeError, %r{but '79', '517' are not prefixed}
end
end

Expand Down