15 changes: 15 additions & 0 deletions manifests/init.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Class: firewall
#
# Manages the installation of packages for operating systems that are
# currently supported by the firewall type.
#
class firewall {
case $::kernel {
'Linux': {
class { "${title}::linux": }
}
default: {
fail("${title}: Kernel '${::kernel}' is not currently supported")
}
}
}
19 changes: 19 additions & 0 deletions manifests/linux.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class firewall::linux {
package { 'iptables':
ensure => present,
}

case $::operatingsystem {
'RedHat', 'CentOS', 'Fedora': {
class { "${title}::redhat":
require => Package['iptables'],
}
}
'Debian', 'Ubuntu': {
class { "${title}::debian":
require => Package['iptables'],
}
}
default: {}
}
}
13 changes: 13 additions & 0 deletions manifests/linux/debian.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class firewall::linux::debian {
package { 'iptables-persistent':
ensure => present,
}

# This isn't a real service/daemon. The start action loads rules, so just
# needs to be called on system boot.
service { 'iptables-persistent':
ensure => undef,
enable => true,
require => Package['iptables-persistent'],
}
}
6 changes: 6 additions & 0 deletions manifests/linux/redhat.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class firewall::linux::redhat {
service { 'iptables':
ensure => running,
enable => true,
}
}
12 changes: 12 additions & 0 deletions spec/classes/firewall_linux_debian_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require 'spec_helper'

describe 'firewall::linux::debian' do
it { should contain_package('iptables-persistent').with(
:ensure => 'present'
)}
it { should contain_service('iptables-persistent').with(
:ensure => nil,
:enable => 'true',
:require => 'Package[iptables-persistent]'
)}
end
8 changes: 8 additions & 0 deletions spec/classes/firewall_linux_redhat_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require 'spec_helper'

describe 'firewall::linux::redhat' do
it { should contain_service('iptables').with(
:ensure => 'running',
:enable => 'true'
)}
end
24 changes: 24 additions & 0 deletions spec/classes/firewall_linux_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require 'spec_helper'

describe 'firewall::linux' do
let(:facts_default) {{ :kernel => 'Linux' }}
it { should contain_package('iptables').with_ensure('present') }

context 'RedHat like' do
%w{RedHat CentOS Fedora}.each do |os|
context "operatingsystem => #{os}" do
let(:facts) { facts_default.merge({ :operatingsystem => os }) }
it { should contain_class('firewall::linux::redhat').with_require('Package[iptables]') }
end
end
end

context 'Debian like' do
%w{Debian Ubuntu}.each do |os|
context "operatingsystem => #{os}" do
let(:facts) { facts_default.merge({ :operatingsystem => os }) }
it { should contain_class('firewall::linux::debian').with_require('Package[iptables]') }
end
end
end
end
8 changes: 8 additions & 0 deletions spec/classes/firewall_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require 'spec_helper'

describe 'firewall' do
context 'kernel => Linux' do
let(:facts) {{ :kernel => 'Linux' }}
it { should include_class('firewall::linux') }
end
end
1 change: 1 addition & 0 deletions spec/fixtures/modules/firewall/lib
1 change: 1 addition & 0 deletions spec/fixtures/modules/firewall/manifests
5 changes: 5 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

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

Bundler.require :default, :test

Expand All @@ -16,6 +17,10 @@
require behaviour.relative_path_from(Pathname.new(dir))
end

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

RSpec.configure do |config|
config.mock_with :mocha
config.module_path = File.join(fixture_path, 'modules')
config.manifest_dir = File.join(fixture_path, 'manifests')
end
32 changes: 32 additions & 0 deletions spec/unit/facter/iptables_persistent_version_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require 'spec_helper'

describe "Facter::Util::Fact iptables_persistent_version" do
before { Facter.clear }
let(:dpkg_cmd) { "dpkg-query -Wf '${Version}' iptables-persistent" }

{
"Debian" => "0.0.20090701",
"Ubuntu" => "0.5.3ubuntu2",
}.each do |os, ver|
describe "#{os} package installed" do
before {
Facter.fact(:operatingsystem).stubs(:value).returns(os)
Facter::Util::Resolution.stubs(:exec).with(dpkg_cmd).returns(ver)
}
it { Facter.fact(:iptables_persistent_version).value.should == ver }
end
end

describe 'Ubuntu package not installed' do
before {
Facter.fact(:operatingsystem).stubs(:value).returns("Ubuntu")
Facter::Util::Resolution.stubs(:exec).with(dpkg_cmd).returns(nil)
}
it { Facter.fact(:iptables_persistent_version).value.should be_nil }
end

describe 'CentOS not supported' do
before { Facter.fact(:operatingsystem).stubs(:value).returns("CentOS") }
it { Facter.fact(:iptables_persistent_version).value.should be_nil }
end
end
34 changes: 34 additions & 0 deletions spec/unit/puppet/type/firewall_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -496,4 +496,38 @@
lambda { @resource[:pkttype] = 'not valid' }.should raise_error(Puppet::Error)
end
end

describe 'autorequire packages' do
[:iptables, :ip6tables].each do |provider|
it "provider #{provider} should autorequire package iptables" do
@resource[:provider] = provider
@resource[:provider].should == provider
package = Puppet::Type.type(:package).new(:name => 'iptables')
catalog = Puppet::Resource::Catalog.new
catalog.add_resource @resource
catalog.add_resource package
rel = @resource.autorequire[0]
rel.source.ref.should == package.ref
rel.target.ref.should == @resource.ref
end

it "provider #{provider} should autorequire packages iptables and iptables-persistent" do
@resource[:provider] = provider
@resource[:provider].should == provider
packages = [
Puppet::Type.type(:package).new(:name => 'iptables'),
Puppet::Type.type(:package).new(:name => 'iptables-persistent')
]
catalog = Puppet::Resource::Catalog.new
catalog.add_resource @resource
packages.each do |package|
catalog.add_resource package
end
packages.zip(@resource.autorequire) do |package, rel|
rel.source.ref.should == package.ref
rel.target.ref.should == @resource.ref
end
end
end
end
end
29 changes: 29 additions & 0 deletions spec/unit/puppet/type/firewallchain_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,33 @@

end

describe 'autorequire packages' do
it "provider iptables_chain should autorequire package iptables" do
resource[:provider].should == :iptables_chain
package = Puppet::Type.type(:package).new(:name => 'iptables')
catalog = Puppet::Resource::Catalog.new
catalog.add_resource resource
catalog.add_resource package
rel = resource.autorequire[0]
rel.source.ref.should == package.ref
rel.target.ref.should == resource.ref
end

it "provider iptables_chain should autorequire packages iptables and iptables-persistent" do
resource[:provider].should == :iptables_chain
packages = [
Puppet::Type.type(:package).new(:name => 'iptables'),
Puppet::Type.type(:package).new(:name => 'iptables-persistent')
]
catalog = Puppet::Resource::Catalog.new
catalog.add_resource resource
packages.each do |package|
catalog.add_resource package
end
packages.zip(resource.autorequire) do |package, rel|
rel.source.ref.should == package.ref
rel.target.ref.should == resource.ref
end
end
end
end
56 changes: 56 additions & 0 deletions spec/unit/puppet/util/firewall_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,60 @@
specify { subject.to_hex32('-1').should == nil }
specify { subject.to_hex32('bananas').should == nil }
end

describe '#persist_iptables' do
before { Facter.clear }
subject { resource }

describe 'when proto is IPv4' do
let(:proto) { 'IPv4' }

it 'should exec for RedHat identified from osfamily' do
Facter.fact(:osfamily).stubs(:value).returns('RedHat')
subject.expects(:execute).with(%w{/sbin/service iptables save})
subject.persist_iptables(proto)
end

it 'should exec for CentOS identified from operatingsystem' do
Facter.fact(:osfamily).stubs(:value).returns(nil)
Facter.fact(:operatingsystem).stubs(:value).returns('CentOS')
subject.expects(:execute).with(%w{/sbin/service iptables save})
subject.persist_iptables(proto)
end

it 'should raise a warning when exec fails' do
Facter.fact(:osfamily).stubs(:value).returns('RedHat')
subject.expects(:execute).with(%w{/sbin/service iptables save}).
raises(Puppet::ExecutionFailure, 'some error')
subject.expects(:warning).with('Unable to persist firewall rules: some error')
subject.persist_iptables(proto)
end
end

describe 'when proto is IPv6' do
let(:proto) { 'IPv6' }

it 'should exec for newer Ubuntu' do
Facter.fact(:osfamily).stubs(:value).returns(nil)
Facter.fact(:operatingsystem).stubs(:value).returns('Ubuntu')
Facter.fact(:iptables_persistent_version).stubs(:value).returns('0.5.3ubuntu2')
subject.expects(:execute).with(%w{/usr/sbin/service iptables-persistent save})
subject.persist_iptables(proto)
end

it 'should not exec for older Ubuntu which does not support IPv6' do
Facter.fact(:osfamily).stubs(:value).returns(nil)
Facter.fact(:operatingsystem).stubs(:value).returns('Ubuntu')
Facter.fact(:iptables_persistent_version).stubs(:value).returns('0.0.20090701')
subject.expects(:execute).never
subject.persist_iptables(proto)
end

it 'should not exec for Suse which is not supported' do
Facter.fact(:osfamily).stubs(:value).returns('Suse')
subject.expects(:execute).never
subject.persist_iptables(proto)
end
end
end
end