8 changes: 6 additions & 2 deletions lib/puppet/type/firewallchain.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

validate do |value|
if value !~ Nameformat then
raise ArgumentError, "Inbuilt chains must be in the form {chain}:{table}:{protocol} where {table} is one of FILTER, NAT, MANGLE, RAW, RAWPOST, BROUTE or empty (alias for filter), chain can be anything without colons or one of PREROUTING, POSTROUTING, BROUTING, INPUT, FORWARD, OUTPUT for the inbuilt chains, and {protocol} being IPv4, IPv6, ethernet (ethernet bridging) got '#{value}' table:'#{$1}' chain:'#{$2}' protocol:'#{$3}'"
raise ArgumentError, "Inbuilt chains must be in the form {chain}:{table}:{protocol} where {table} is one of FILTER, NAT, MANGLE, RAW, RAWPOST, BROUTE, SECURITY or empty (alias for filter), chain can be anything without colons or one of PREROUTING, POSTROUTING, BROUTING, INPUT, FORWARD, OUTPUT for the inbuilt chains, and {protocol} being IPv4, IPv6, ethernet (ethernet bridging) got '#{value}' table:'#{$1}' chain:'#{$2}' protocol:'#{$3}'"
else
chain = $1
table = $2
Expand All @@ -59,7 +59,7 @@
if chain =~ /^(BROUTING|FORWARD)$/
raise ArgumentError, "PREROUTING, POSTROUTING, INPUT, and OUTPUT are the only inbuilt chains that can be used in table 'nat'"
end
if protocol =~/^(IP(v6)?)?$/
if Gem::Version.new(Facter['kernelmajversion'].value.dup) < Gem::Version.new('3.7') and protocol =~/^(IP(v6)?)?$/
raise ArgumentError, "table nat isn't valid in IPv6. You must specify ':IPv4' as the name suffix"
end
when 'raw'
Expand All @@ -73,6 +73,10 @@
if chain =~ /^PREROUTING|POSTROUTING|INPUT|FORWARD|OUTPUT$/
raise ArgumentError,'BROUTING is the only inbuilt chain allowed on on table \'broute\''
end
when 'security'
if chain =~ /^(PREROUTING|POSTROUTING|BROUTING)$/
raise ArgumentError, "INPUT, OUTPUT and FORWARD are the only inbuilt chains that can be used in table 'security'"
end
end
if chain == 'BROUTING' && ( protocol != 'ethernet' || table!='broute')
raise ArgumentError,'BROUTING is the only inbuilt chain allowed on on table \'BROUTE\' with protocol \'ethernet\' i.e. \'broute:BROUTING:enternet\''
Expand Down
3 changes: 3 additions & 0 deletions lib/puppet/util/firewall.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ def persist_iptables(proto)

# Older iptables-persistent doesn't provide save action.
if os_key == 'Debian'
# We need to call flush to clear Facter cache as it's possible the cached value will be nil due to the fact
# that the iptables-persistent package was potentially installed after the initial Fact gathering.
Facter.fact(:iptables_persistent_version).flush
persist_ver = Facter.value(:iptables_persistent_version)
if (persist_ver and Puppet::Util::Package.versioncmp(persist_ver, '0.5.0') < 0)
os_key = 'Debian_manual'
Expand Down
2 changes: 2 additions & 0 deletions manifests/init.pp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#
class firewall (
$ensure = running,
$pkg_ensure = present,
$service_name = $::firewall::params::service_name,
$package_name = $::firewall::params::package_name,
) inherits ::firewall::params {
Expand All @@ -29,6 +30,7 @@
'Linux': {
class { "${title}::linux":
ensure => $ensure,
pkg_ensure => $pkg_ensure,
service_name => $service_name,
package_name => $package_name,
}
Expand Down
3 changes: 2 additions & 1 deletion manifests/linux.pp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#
class firewall::linux (
$ensure = running,
$pkg_ensure = present,
$service_name = $::firewall::params::service_name,
$package_name = $::firewall::params::package_name,
) inherits ::firewall::params {
Expand All @@ -22,7 +23,7 @@
}

package { 'iptables':
ensure => present,
ensure => $pkg_ensure,
}

case $::operatingsystem {
Expand Down
11 changes: 6 additions & 5 deletions manifests/linux/archlinux.pp
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@
# Default: true
#
class firewall::linux::archlinux (
$ensure = 'running',
$enable = true,
$service_name = $::firewall::params::service_name,
$package_name = $::firewall::params::package_name,
$ensure = 'running',
$enable = true,
$service_name = $::firewall::params::service_name,
$package_name = $::firewall::params::package_name,
$package_ensure = $::firewall::params::package_ensure,
) inherits ::firewall::params {
if $package_name {
package { $package_name:
ensure => $ensure,
ensure => $package_ensure,
}
}

Expand Down
11 changes: 6 additions & 5 deletions manifests/linux/debian.pp
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
# Default: true
#
class firewall::linux::debian (
$ensure = running,
$enable = true,
$service_name = $::firewall::params::service_name,
$package_name = $::firewall::params::package_name,
$ensure = running,
$enable = true,
$service_name = $::firewall::params::service_name,
$package_name = $::firewall::params::package_name,
$package_ensure = $::firewall::params::package_ensure,
) inherits ::firewall::params {

if $package_name {
Expand All @@ -27,7 +28,7 @@
refreshonly => true
}
package { $package_name:
ensure => present,
ensure => $package_ensure,
require => Exec['iptables-persistent-debconf']
}
}
Expand Down
11 changes: 6 additions & 5 deletions manifests/linux/gentoo.pp
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@
# Default: true
#
class firewall::linux::gentoo (
$ensure = 'running',
$enable = true,
$service_name = $::firewall::params::service_name,
$package_name = $::firewall::params::package_name,
$ensure = 'running',
$enable = true,
$service_name = $::firewall::params::service_name,
$package_name = $::firewall::params::package_name,
$package_ensure = $::firewall::params::package_ensure,
) inherits ::firewall::params {
if $package_name {
package { $package_name:
ensure => present,
ensure => $package_ensure,
}
}

Expand Down
24 changes: 15 additions & 9 deletions manifests/linux/redhat.pp
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
# Default: true
#
class firewall::linux::redhat (
$ensure = running,
$enable = true,
$service_name = $::firewall::params::service_name,
$package_name = $::firewall::params::package_name,
$ensure = running,
$enable = true,
$service_name = $::firewall::params::service_name,
$package_name = $::firewall::params::package_name,
$package_ensure = $::firewall::params::package_ensure,
) inherits ::firewall::params {

# RHEL 7 and later and Fedora 15 and later require the iptables-services
Expand All @@ -34,7 +35,7 @@

if $package_name {
package { $package_name:
ensure => present,
ensure => $package_ensure,
before => Service[$service_name],
}
}
Expand All @@ -46,7 +47,7 @@
exec { '/usr/bin/systemctl daemon-reload':
require => Package[$package_name],
before => Service[$service_name],
unless => '/usr/bin/systemctl is-active iptables'
unless => "/usr/bin/systemctl is-active ${service_name}",
}
}
}
Expand All @@ -55,18 +56,23 @@
ensure => $ensure,
enable => $enable,
hasstatus => true,
require => File['/etc/sysconfig/iptables'],
require => File["/etc/sysconfig/${service_name}"],
}

# Redhat 7 selinux user context for /etc/sysconfig/iptables is set to unconfined_u
case $::selinux {
#lint:ignore:quoted_booleans
'true',true: { $seluser = 'unconfined_u' }
'true',true: {
case $::operatingsystemrelease {
/^(6|7)\..*/: { $seluser = 'unconfined_u' }
default: { $seluser = 'system_u' }
}
}
#lint:endignore
default: { $seluser = undef }
}

file { '/etc/sysconfig/iptables':
file { "/etc/sysconfig/${service_name}":
ensure => present,
owner => 'root',
group => 'root',
Expand Down
1 change: 1 addition & 0 deletions manifests/params.pp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
class firewall::params {
$package_ensure = 'present'
case $::osfamily {
'RedHat': {
case $::operatingsystem {
Expand Down
2 changes: 1 addition & 1 deletion metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "puppetlabs-firewall",
"version": "1.7.2",
"version": "1.8.0",
"author": "Puppet Labs",
"summary": "Manages Firewalls such as iptables",
"license": "Apache-2.0",
Expand Down
2 changes: 2 additions & 0 deletions spec/acceptance/connlimit_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class { '::firewall': }
EOS

apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => do_catch_changes)
end

it 'should contain the rule' do
Expand All @@ -52,6 +53,7 @@ class { '::firewall': }
EOS

apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => do_catch_changes)
end

it 'should contain the rule' do
Expand Down
41 changes: 41 additions & 0 deletions spec/acceptance/firewall_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2330,6 +2330,47 @@ class { '::firewall': }
end
end

context 'log_uid is true' do
it 'adds the rule' do
pp = <<-EOS
class { '::firewall': }
firewall { '700 - test log_uid':
chain => 'OUTPUT',
jump => 'LOG',
log_uid => true,
}
EOS

apply_manifest(pp, :catch_failures => true)
end

it 'should contain the rule' do
shell('iptables-save') do |r|
expect(r.stdout).to match(/-A OUTPUT -p tcp -m comment --comment "700 - test log_uid" -j LOG --log-uid/)
end
end

it 'removes the rule' do
pp = <<-EOS
class { '::firewall': }
firewall { '700 - test log_uid':
chain => 'OUTPUT',
jump => 'LOG',
log_uid => false,
ensure => absent,
}
EOS

apply_manifest(pp, :catch_failures => true)
end

it 'should not contain the rule' do
shell('iptables-save') do |r|
expect(r.stdout).to_not match(/-A OUTPUT -p tcp -m comment --comment "700 - test log_uid" -j --log-uid/)
end
end
end

context 'comment containing "-A "' do
it 'adds the rule' do
pp = <<-EOS
Expand Down
29 changes: 29 additions & 0 deletions spec/acceptance/nodesets/new/aio/debian-8-64mda.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
HOSTS:
debian-8-amd64-agent:
roles:
- agent
- default
platform: debian-8-amd64
template: debian-8-x86_64
hypervisor: vcloud
redhat-7-x86_64-master:
roles:
- master
- dashboard
- database
- agent
platform: el-7-x86_64
template: redhat-7-x86_64
hypervisor: vcloud
CONFIG:
nfs_server: none
consoleport: 443
datastore: instance0
folder: Delivery/Quality Assurance/Enterprise/Dynamic
resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
pooling_api: http://vcloud.delivery.puppetlabs.net/
type: aio
ssh:
timeout: 600

28 changes: 28 additions & 0 deletions spec/acceptance/nodesets/new/pe/debian-8-64mda.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
HOSTS:
debian-8-amd64-agent:
roles:
- agent
- default
platform: debian-8-amd64
template: debian-8-x86_64
hypervisor: vcloud
redhat-7-x86_64-master:
roles:
- master
- dashboard
- database
- agent
platform: el-7-x86_64
template: redhat-7-x86_64
hypervisor: vcloud
CONFIG:
nfs_server: none
consoleport: 443
datastore: instance0
folder: Delivery/Quality Assurance/Enterprise/Dynamic
resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
pooling_api: http://vcloud.delivery.puppetlabs.net/
ssh:
timeout: 600

8 changes: 8 additions & 0 deletions spec/fixtures/iptables/conversion_hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,14 @@
:clamp_mss_to_pmtu => true,
},
},
'mangled_chain_name_with_-f' => {
:line => '-A foo-filter -p tcp -m comment --comment "068 chain name containing -f" -j ACCEPT',
:params => {
:name => '068 chain name containing -f',
:action => 'accept',
:chain => 'foo-filter',
},
},
}

# This hash is for testing converting a hash to an argument line.
Expand Down
33 changes: 5 additions & 28 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,30 +1,7 @@
dir = File.expand_path(File.dirname(__FILE__))
$LOAD_PATH.unshift File.join(dir, 'lib')
require 'puppetlabs_spec_helper/module_spec_helper'

# Don't want puppet getting the command line arguments for rake or autotest
ARGV.clear

require 'rubygems'
require 'bundler/setup'
require 'rspec-puppet'

Bundler.require :default, :test

require 'pathname'
require 'tmpdir'

Pathname.glob("#{dir}/shared_behaviours/**/*.rb") do |behaviour|
require behaviour.relative_path_from(Pathname.new(dir))
end

fixture_path = File.expand_path(File.join(__FILE__, '..', 'fixtures'))

RSpec.configure do |config|
config.tty = true
config.mock_with :rspec do |c|
c.syntax = :expect
end
config.module_path = File.join(fixture_path, 'modules')
config.manifest_dir = File.join(fixture_path, 'manifests')
config.environmentpath = File.expand_path(File.join(Dir.pwd, 'spec'))
# put local configuration and setup into spec_helper_local
begin
require 'spec_helper_local'
rescue LoadError
end
3 changes: 3 additions & 0 deletions spec/spec_helper_local.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
RSpec.configure do |config|
config.mock_with :rspec
end
6 changes: 6 additions & 0 deletions spec/unit/puppet/provider/iptables_chain_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@
'NAT:mangle:IPv4',
'NAT:mangle:IPv4',
'NAT:mangle:IPv4',
'security:INPUT:IPv4',
'security:FORWARD:IPv4',
'security:OUTPUT:IPv4',
':$5()*&%\'"^$): :IPv4',
]
allow(provider).to receive(:execute).with(['/sbin/iptables-save']).and_return('
Expand Down Expand Up @@ -184,6 +187,9 @@
'mangle:OUTPUT:IPv6',
'mangle:POSTROUTING:IPv6',
'mangle:ff:IPv6',
'security:INPUT:IPv6',
'security:FORWARD:IPv6',
'security:OUTPUT:IPv6',
':INPUT:IPv6',
':FORWARD:IPv6',
':OUTPUT:IPv6',
Expand Down
2 changes: 1 addition & 1 deletion spec/unit/puppet/type/firewall_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@

describe 'port deprecated' do
it "raises a warning" do
expect(Puppet).to receive(:warning).with /port is deprecated/
expect(Puppet).to receive(:warning).with /port to firewall is deprecated/
@resource[:port] = "22"
end
end
Expand Down
11 changes: 9 additions & 2 deletions spec/unit/puppet/type/firewallchain_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,20 @@
'mangle' => [ 'PREROUTING', 'POSTROUTING', 'INPUT', 'FORWARD', 'OUTPUT' ],
'filter' => ['INPUT','OUTPUT','FORWARD'],
'raw' => [ 'PREROUTING', 'OUTPUT'],
'broute' => ['BROUTING']
'broute' => ['BROUTING'],
'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'
it "should fail #{name}" do
it "should accept #{name} for Linux 3.7+" do
allow(Facter.fact(:kernelmajversion)).to receive(:value).and_return('3.7')
resource[:name] = name
resource[:name].should == name
end
it "should fail #{name} for Linux 2.6" do
allow(Facter.fact(:kernelmajversion)).to receive(:value).and_return('2.6')
expect { resource[:name] = name }.to raise_error(Puppet::Error)
end
elsif protocol != 'ethernet' && table == 'broute'
Expand Down