Added puppetlabs-firewall (required by puppetlabs-postgresql), updated the other modules.
This commit is contained in:
parent
5f4b7a3b72
commit
dee66abcdd
137 changed files with 11118 additions and 419 deletions
77
modules/firewall/spec/acceptance/change_source_spec.rb
Normal file
77
modules/firewall/spec/acceptance/change_source_spec.rb
Normal file
|
@ -0,0 +1,77 @@
|
|||
require 'spec_helper_acceptance'
|
||||
|
||||
describe 'firewall type', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
|
||||
describe 'reset' do
|
||||
it 'deletes all rules' do
|
||||
shell('iptables --flush; iptables -t nat --flush; iptables -t mangle --flush')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when unmanaged rules exist' do
|
||||
it 'applies with 8.0.0.1 first' do
|
||||
pp = <<-EOS
|
||||
class { '::firewall': }
|
||||
firewall { '101 test source changes':
|
||||
proto => tcp,
|
||||
port => '101',
|
||||
action => accept,
|
||||
source => '8.0.0.1',
|
||||
}
|
||||
firewall { '100 test source static':
|
||||
proto => tcp,
|
||||
port => '100',
|
||||
action => accept,
|
||||
source => '8.0.0.2',
|
||||
}
|
||||
EOS
|
||||
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
end
|
||||
|
||||
it 'adds a unmanaged rule without a comment' do
|
||||
shell('iptables -A INPUT -t filter -s 8.0.0.3/32 -p tcp -m multiport --ports 102 -j ACCEPT')
|
||||
expect(shell('iptables-save').stdout).to match(/-A INPUT -s 8\.0\.0\.3(\/32)? -p tcp -m multiport --ports 102 -j ACCEPT/)
|
||||
end
|
||||
|
||||
it 'contains the changable 8.0.0.1 rule' do
|
||||
shell('iptables-save') do |r|
|
||||
expect(r.stdout).to match(/-A INPUT -s 8\.0\.0\.1(\/32)? -p tcp -m multiport --ports 101 -m comment --comment "101 test source changes" -j ACCEPT/)
|
||||
end
|
||||
end
|
||||
it 'contains the static 8.0.0.2 rule' do
|
||||
shell('iptables-save') do |r|
|
||||
expect(r.stdout).to match(/-A INPUT -s 8\.0\.0\.2(\/32)? -p tcp -m multiport --ports 100 -m comment --comment "100 test source static" -j ACCEPT/)
|
||||
end
|
||||
end
|
||||
|
||||
it 'changes to 8.0.0.4 second' do
|
||||
pp = <<-EOS
|
||||
class { '::firewall': }
|
||||
firewall { '101 test source changes':
|
||||
proto => tcp,
|
||||
port => '101',
|
||||
action => accept,
|
||||
source => '8.0.0.4',
|
||||
}
|
||||
EOS
|
||||
|
||||
expect(apply_manifest(pp, :catch_failures => true).stdout).to match(/Notice: \/Stage\[main\]\/Main\/Firewall\[101 test source changes\]\/source: source changed '8\.0\.0\.1\/32' to '8\.0\.0\.4\/32'/)
|
||||
end
|
||||
|
||||
it 'does not contain the old changing 8.0.0.1 rule' do
|
||||
shell('iptables-save') do |r|
|
||||
expect(r.stdout).to_not match(/8\.0\.0\.1/)
|
||||
end
|
||||
end
|
||||
it 'contains the staic 8.0.0.2 rule' do
|
||||
shell('iptables-save') do |r|
|
||||
expect(r.stdout).to match(/-A INPUT -s 8\.0\.0\.2(\/32)? -p tcp -m multiport --ports 100 -m comment --comment "100 test source static" -j ACCEPT/)
|
||||
end
|
||||
end
|
||||
it 'contains the changing new 8.0.0.4 rule' do
|
||||
shell('iptables-save') do |r|
|
||||
expect(r.stdout).to match(/-A INPUT -s 8\.0\.0\.4(\/32)? -p tcp -m multiport --ports 101 -m comment --comment "101 test source changes" -j ACCEPT/)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
27
modules/firewall/spec/acceptance/class_spec.rb
Normal file
27
modules/firewall/spec/acceptance/class_spec.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
require 'spec_helper_acceptance'
|
||||
|
||||
describe "firewall class:", :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
|
||||
it 'should run successfully' do
|
||||
pp = "class { 'firewall': }"
|
||||
|
||||
# Run it twice and test for idempotency
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
|
||||
end
|
||||
|
||||
it 'ensure => stopped:' do
|
||||
pp = "class { 'firewall': ensure => stopped }"
|
||||
|
||||
# Run it twice and test for idempotency
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
|
||||
end
|
||||
|
||||
it 'ensure => running:' do
|
||||
pp = "class { 'firewall': ensure => running }"
|
||||
|
||||
# Run it twice and test for idempotency
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
|
||||
end
|
||||
end
|
55
modules/firewall/spec/acceptance/connlimit_spec.rb
Normal file
55
modules/firewall/spec/acceptance/connlimit_spec.rb
Normal file
|
@ -0,0 +1,55 @@
|
|||
require 'spec_helper_acceptance'
|
||||
|
||||
describe 'firewall type', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
|
||||
|
||||
describe 'connlimit_above' do
|
||||
context '10' do
|
||||
it 'applies' do
|
||||
pp = <<-EOS
|
||||
class { '::firewall': }
|
||||
firewall { '500 - test':
|
||||
proto => tcp,
|
||||
dport => '22',
|
||||
connlimit_above => '10',
|
||||
action => reject,
|
||||
}
|
||||
EOS
|
||||
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
end
|
||||
|
||||
it 'should contain the rule' do
|
||||
shell('iptables-save') do |r|
|
||||
#connlimit-saddr is added in Ubuntu 14.04.
|
||||
expect(r.stdout).to match(/-A INPUT -p tcp -m multiport --dports 22 -m comment --comment "500 - test" -m connlimit --connlimit-above 10 --connlimit-mask 32 (--connlimit-saddr )?-j REJECT --reject-with icmp-port-unreachable/)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'connlimit_mask' do
|
||||
context '24' do
|
||||
it 'applies' do
|
||||
pp = <<-EOS
|
||||
class { '::firewall': }
|
||||
firewall { '501 - test':
|
||||
proto => tcp,
|
||||
dport => '22',
|
||||
connlimit_above => '10',
|
||||
connlimit_mask => '24',
|
||||
action => reject,
|
||||
}
|
||||
EOS
|
||||
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
end
|
||||
|
||||
it 'should contain the rule' do
|
||||
shell('iptables-save') do |r|
|
||||
#connlimit-saddr is added in Ubuntu 14.04.
|
||||
expect(r.stdout).to match(/-A INPUT -p tcp -m multiport --dports 22 -m comment --comment "501 - test" -m connlimit --connlimit-above 10 --connlimit-mask 24 (--connlimit-saddr )?-j REJECT --reject-with icmp-port-unreachable/)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
27
modules/firewall/spec/acceptance/connmark_spec.rb
Normal file
27
modules/firewall/spec/acceptance/connmark_spec.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
require 'spec_helper_acceptance'
|
||||
|
||||
describe 'firewall type', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
|
||||
|
||||
describe 'connmark' do
|
||||
context '50' do
|
||||
it 'applies' do
|
||||
pp = <<-EOS
|
||||
class { '::firewall': }
|
||||
firewall { '502 - test':
|
||||
proto => 'all',
|
||||
connmark => '0x1',
|
||||
action => reject,
|
||||
}
|
||||
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 INPUT -m comment --comment "502 - test" -m connmark --mark 0x1 -j REJECT --reject-with icmp-port-unreachable/)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
1618
modules/firewall/spec/acceptance/firewall_spec.rb
Normal file
1618
modules/firewall/spec/acceptance/firewall_spec.rb
Normal file
File diff suppressed because it is too large
Load diff
125
modules/firewall/spec/acceptance/firewallchain_spec.rb
Normal file
125
modules/firewall/spec/acceptance/firewallchain_spec.rb
Normal file
|
@ -0,0 +1,125 @@
|
|||
require 'spec_helper_acceptance'
|
||||
|
||||
describe 'puppet resource firewallchain command:', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
|
||||
before :all do
|
||||
iptables_flush_all_tables
|
||||
end
|
||||
describe 'ensure' do
|
||||
context 'present' do
|
||||
it 'applies cleanly' do
|
||||
pp = <<-EOS
|
||||
firewallchain { 'MY_CHAIN:filter:IPv4':
|
||||
ensure => present,
|
||||
}
|
||||
EOS
|
||||
# Run it twice and test for idempotency
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
apply_manifest(pp, :catch_changes => true)
|
||||
end
|
||||
|
||||
it 'finds the chain' do
|
||||
shell('iptables-save') do |r|
|
||||
expect(r.stdout).to match(/MY_CHAIN/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'absent' do
|
||||
it 'applies cleanly' do
|
||||
pp = <<-EOS
|
||||
firewallchain { 'MY_CHAIN:filter:IPv4':
|
||||
ensure => absent,
|
||||
}
|
||||
EOS
|
||||
# Run it twice and test for idempotency
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
apply_manifest(pp, :catch_changes => true)
|
||||
end
|
||||
|
||||
it 'fails to find the chain' do
|
||||
shell('iptables-save') do |r|
|
||||
expect(r.stdout).to_not match(/MY_CHAIN/)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# XXX purge => false is not yet implemented
|
||||
#context 'adding a firewall rule to a chain:' do
|
||||
# it 'applies cleanly' do
|
||||
# pp = <<-EOS
|
||||
# firewallchain { 'MY_CHAIN:filter:IPv4':
|
||||
# ensure => present,
|
||||
# }
|
||||
# firewall { '100 my rule':
|
||||
# chain => 'MY_CHAIN',
|
||||
# action => 'accept',
|
||||
# proto => 'tcp',
|
||||
# dport => 5000,
|
||||
# }
|
||||
# EOS
|
||||
# # Run it twice and test for idempotency
|
||||
# apply_manifest(pp, :catch_failures => true)
|
||||
# apply_manifest(pp, :catch_changes => true)
|
||||
# end
|
||||
#end
|
||||
|
||||
#context 'not purge firewallchain chains:' do
|
||||
# it 'does not purge the rule' do
|
||||
# pp = <<-EOS
|
||||
# firewallchain { 'MY_CHAIN:filter:IPv4':
|
||||
# ensure => present,
|
||||
# purge => false,
|
||||
# before => Resources['firewall'],
|
||||
# }
|
||||
# resources { 'firewall':
|
||||
# purge => true,
|
||||
# }
|
||||
# EOS
|
||||
# # Run it twice and test for idempotency
|
||||
# apply_manifest(pp, :catch_failures => true) do |r|
|
||||
# expect(r.stdout).to_not match(/removed/)
|
||||
# expect(r.stderr).to eq('')
|
||||
# end
|
||||
# apply_manifest(pp, :catch_changes => true)
|
||||
# end
|
||||
|
||||
# it 'still has the rule' do
|
||||
# pp = <<-EOS
|
||||
# firewall { '100 my rule':
|
||||
# chain => 'MY_CHAIN',
|
||||
# action => 'accept',
|
||||
# proto => 'tcp',
|
||||
# dport => 5000,
|
||||
# }
|
||||
# EOS
|
||||
# # Run it twice and test for idempotency
|
||||
# apply_manifest(pp, :catch_changes => true)
|
||||
# end
|
||||
#end
|
||||
|
||||
describe 'policy' do
|
||||
after :all do
|
||||
shell('iptables -t filter -P FORWARD ACCEPT')
|
||||
end
|
||||
|
||||
context 'DROP' do
|
||||
it 'applies cleanly' do
|
||||
pp = <<-EOS
|
||||
firewallchain { 'FORWARD:filter:IPv4':
|
||||
policy => 'drop',
|
||||
}
|
||||
EOS
|
||||
# Run it twice and test for idempotency
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
apply_manifest(pp, :catch_changes => true)
|
||||
end
|
||||
|
||||
it 'finds the chain' do
|
||||
shell('iptables-save') do |r|
|
||||
expect(r.stdout).to match(/FORWARD DROP/)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
114
modules/firewall/spec/acceptance/ip6_fragment_spec.rb
Normal file
114
modules/firewall/spec/acceptance/ip6_fragment_spec.rb
Normal file
|
@ -0,0 +1,114 @@
|
|||
require 'spec_helper_acceptance'
|
||||
|
||||
if default['platform'] =~ /el-5/
|
||||
describe "firewall ip6tables doesn't work on 1.3.5 because --comment is missing", :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
|
||||
before :all do
|
||||
ip6tables_flush_all_tables
|
||||
end
|
||||
|
||||
it "can't use ip6tables" do
|
||||
pp = <<-EOS
|
||||
class { '::firewall': }
|
||||
firewall { '599 - test':
|
||||
ensure => present,
|
||||
proto => 'tcp',
|
||||
provider => 'ip6tables',
|
||||
}
|
||||
EOS
|
||||
expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/ip6tables provider is not supported/)
|
||||
end
|
||||
end
|
||||
else
|
||||
describe 'firewall ishasmorefrags/islastfrag/isfirstfrag properties', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
|
||||
before :all do
|
||||
ip6tables_flush_all_tables
|
||||
end
|
||||
|
||||
shared_examples "is idempotent" do |values, line_match|
|
||||
it "changes the values to #{values}" do
|
||||
pp = <<-EOS
|
||||
class { '::firewall': }
|
||||
firewall { '599 - test':
|
||||
ensure => present,
|
||||
proto => 'tcp',
|
||||
provider => 'ip6tables',
|
||||
#{values}
|
||||
}
|
||||
EOS
|
||||
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
apply_manifest(pp, :catch_changes => true)
|
||||
|
||||
shell('ip6tables-save') do |r|
|
||||
expect(r.stdout).to match(/#{line_match}/)
|
||||
end
|
||||
end
|
||||
end
|
||||
shared_examples "doesn't change" do |values, line_match|
|
||||
it "doesn't change the values to #{values}" do
|
||||
pp = <<-EOS
|
||||
class { '::firewall': }
|
||||
firewall { '599 - test':
|
||||
ensure => present,
|
||||
proto => 'tcp',
|
||||
provider => 'ip6tables',
|
||||
#{values}
|
||||
}
|
||||
EOS
|
||||
|
||||
apply_manifest(pp, :catch_changes => true)
|
||||
|
||||
shell('ip6tables-save') do |r|
|
||||
expect(r.stdout).to match(/#{line_match}/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'adding a rule' do
|
||||
context 'when unset' do
|
||||
before :all do
|
||||
ip6tables_flush_all_tables
|
||||
end
|
||||
it_behaves_like 'is idempotent', '', /-A INPUT -p tcp -m comment --comment "599 - test"/
|
||||
end
|
||||
context 'when set to true' do
|
||||
before :all do
|
||||
ip6tables_flush_all_tables
|
||||
end
|
||||
it_behaves_like "is idempotent", 'ishasmorefrags => true, islastfrag => true, isfirstfrag => true', /-A INPUT -p tcp -m frag --fragid 0 --fragmore -m frag --fragid 0 --fraglast -m frag --fragid 0 --fragfirst -m comment --comment "599 - test"/
|
||||
end
|
||||
context 'when set to false' do
|
||||
before :all do
|
||||
ip6tables_flush_all_tables
|
||||
end
|
||||
it_behaves_like "is idempotent", 'ishasmorefrags => false, islastfrag => false, isfirstfrag => false', /-A INPUT -p tcp -m comment --comment "599 - test"/
|
||||
end
|
||||
end
|
||||
describe 'editing a rule' do
|
||||
context 'when unset or false' do
|
||||
before :each do
|
||||
ip6tables_flush_all_tables
|
||||
shell('ip6tables -A INPUT -p tcp -m comment --comment "599 - test"')
|
||||
end
|
||||
context 'and current value is false' do
|
||||
it_behaves_like "doesn't change", 'ishasmorefrags => false, islastfrag => false, isfirstfrag => false', /-A INPUT -p tcp -m comment --comment "599 - test"/
|
||||
end
|
||||
context 'and current value is true' do
|
||||
it_behaves_like "is idempotent", 'ishasmorefrags => true, islastfrag => true, isfirstfrag => true', /-A INPUT -p tcp -m frag --fragid 0 --fragmore -m frag --fragid 0 --fraglast -m frag --fragid 0 --fragfirst -m comment --comment "599 - test"/
|
||||
end
|
||||
end
|
||||
context 'when set to true' do
|
||||
before :each do
|
||||
ip6tables_flush_all_tables
|
||||
shell('ip6tables -A INPUT -p tcp -m frag --fragid 0 --fragmore -m frag --fragid 0 --fraglast -m frag --fragid 0 --fragfirst -m comment --comment "599 - test"')
|
||||
end
|
||||
context 'and current value is false' do
|
||||
it_behaves_like "is idempotent", 'ishasmorefrags => false, islastfrag => false, isfirstfrag => false', /-A INPUT -p tcp -m comment --comment "599 - test"/
|
||||
end
|
||||
context 'and current value is true' do
|
||||
it_behaves_like "doesn't change", 'ishasmorefrags => true, islastfrag => true, isfirstfrag => true', /-A INPUT -p tcp -m frag --fragid 0 --fragmore -m frag --fragid 0 --fraglast -m frag --fragid 0 --fragfirst -m comment --comment "599 - test"/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
92
modules/firewall/spec/acceptance/isfragment_spec.rb
Normal file
92
modules/firewall/spec/acceptance/isfragment_spec.rb
Normal file
|
@ -0,0 +1,92 @@
|
|||
require 'spec_helper_acceptance'
|
||||
|
||||
describe 'firewall isfragment property', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
|
||||
before :all do
|
||||
iptables_flush_all_tables
|
||||
end
|
||||
|
||||
shared_examples "is idempotent" do |value, line_match|
|
||||
it "changes the value to #{value}" do
|
||||
pp = <<-EOS
|
||||
class { '::firewall': }
|
||||
firewall { '597 - test':
|
||||
ensure => present,
|
||||
proto => 'tcp',
|
||||
#{value}
|
||||
}
|
||||
EOS
|
||||
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
apply_manifest(pp, :catch_changes => true)
|
||||
|
||||
shell('iptables-save') do |r|
|
||||
expect(r.stdout).to match(/#{line_match}/)
|
||||
end
|
||||
end
|
||||
end
|
||||
shared_examples "doesn't change" do |value, line_match|
|
||||
it "doesn't change the value to #{value}" do
|
||||
pp = <<-EOS
|
||||
class { '::firewall': }
|
||||
firewall { '597 - test':
|
||||
ensure => present,
|
||||
proto => 'tcp',
|
||||
#{value}
|
||||
}
|
||||
EOS
|
||||
|
||||
apply_manifest(pp, :catch_changes => true)
|
||||
|
||||
shell('iptables-save') do |r|
|
||||
expect(r.stdout).to match(/#{line_match}/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'adding a rule' do
|
||||
context 'when unset' do
|
||||
before :all do
|
||||
iptables_flush_all_tables
|
||||
end
|
||||
it_behaves_like 'is idempotent', '', /-A INPUT -p tcp -m comment --comment "597 - test"/
|
||||
end
|
||||
context 'when set to true' do
|
||||
before :all do
|
||||
iptables_flush_all_tables
|
||||
end
|
||||
it_behaves_like 'is idempotent', 'isfragment => true,', /-A INPUT -p tcp -f -m comment --comment "597 - test"/
|
||||
end
|
||||
context 'when set to false' do
|
||||
before :all do
|
||||
iptables_flush_all_tables
|
||||
end
|
||||
it_behaves_like "is idempotent", 'isfragment => false,', /-A INPUT -p tcp -m comment --comment "597 - test"/
|
||||
end
|
||||
end
|
||||
describe 'editing a rule' do
|
||||
context 'when unset or false' do
|
||||
before :each do
|
||||
iptables_flush_all_tables
|
||||
shell('iptables -A INPUT -p tcp -m comment --comment "597 - test"')
|
||||
end
|
||||
context 'and current value is false' do
|
||||
it_behaves_like "doesn't change", 'isfragment => false,', /-A INPUT -p tcp -m comment --comment "597 - test"/
|
||||
end
|
||||
context 'and current value is true' do
|
||||
it_behaves_like "is idempotent", 'isfragment => true,', /-A INPUT -p tcp -f -m comment --comment "597 - test"/
|
||||
end
|
||||
end
|
||||
context 'when set to true' do
|
||||
before :each do
|
||||
iptables_flush_all_tables
|
||||
shell('iptables -A INPUT -p tcp -f -m comment --comment "597 - test"')
|
||||
end
|
||||
context 'and current value is false' do
|
||||
it_behaves_like "is idempotent", 'isfragment => false,', /-A INPUT -p tcp -m comment --comment "597 - test"/
|
||||
end
|
||||
context 'and current value is true' do
|
||||
it_behaves_like "doesn't change", 'isfragment => true,', /-A INPUT -p tcp -f -m comment --comment "597 - test"/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
HOSTS:
|
||||
centos-59-x64:
|
||||
roles:
|
||||
- master
|
||||
- database
|
||||
- console
|
||||
platform: el-5-x86_64
|
||||
box : centos-59-x64-vbox4210-nocm
|
||||
box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-59-x64-vbox4210-nocm.box
|
||||
hypervisor : vagrant
|
||||
CONFIG:
|
||||
type: pe
|
10
modules/firewall/spec/acceptance/nodesets/centos-59-x64.yml
Normal file
10
modules/firewall/spec/acceptance/nodesets/centos-59-x64.yml
Normal file
|
@ -0,0 +1,10 @@
|
|||
HOSTS:
|
||||
centos-59-x64:
|
||||
roles:
|
||||
- master
|
||||
platform: el-5-x86_64
|
||||
box : centos-59-x64-vbox4210-nocm
|
||||
box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-59-x64-vbox4210-nocm.box
|
||||
hypervisor : vagrant
|
||||
CONFIG:
|
||||
type: foss
|
|
@ -0,0 +1,10 @@
|
|||
HOSTS:
|
||||
centos-64-x64:
|
||||
roles:
|
||||
- master
|
||||
platform: el-6-x86_64
|
||||
box : centos-64-x64-fusion503-nocm
|
||||
box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-fusion503-nocm.box
|
||||
hypervisor : fusion
|
||||
CONFIG:
|
||||
type: foss
|
|
@ -0,0 +1,12 @@
|
|||
HOSTS:
|
||||
centos-64-x64:
|
||||
roles:
|
||||
- master
|
||||
- database
|
||||
- dashboard
|
||||
platform: el-6-x86_64
|
||||
box : centos-64-x64-vbox4210-nocm
|
||||
box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
|
||||
hypervisor : vagrant
|
||||
CONFIG:
|
||||
type: pe
|
10
modules/firewall/spec/acceptance/nodesets/centos-64-x64.yml
Normal file
10
modules/firewall/spec/acceptance/nodesets/centos-64-x64.yml
Normal file
|
@ -0,0 +1,10 @@
|
|||
HOSTS:
|
||||
centos-64-x64:
|
||||
roles:
|
||||
- master
|
||||
platform: el-6-x86_64
|
||||
box : centos-64-x64-vbox4210-nocm
|
||||
box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
|
||||
hypervisor : vagrant
|
||||
CONFIG:
|
||||
type: foss
|
10
modules/firewall/spec/acceptance/nodesets/debian-607-x64.yml
Normal file
10
modules/firewall/spec/acceptance/nodesets/debian-607-x64.yml
Normal file
|
@ -0,0 +1,10 @@
|
|||
HOSTS:
|
||||
debian-607-x64:
|
||||
roles:
|
||||
- master
|
||||
platform: debian-6-amd64
|
||||
box : debian-607-x64-vbox4210-nocm
|
||||
box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-607-x64-vbox4210-nocm.box
|
||||
hypervisor : vagrant
|
||||
CONFIG:
|
||||
type: git
|
|
@ -0,0 +1,10 @@
|
|||
HOSTS:
|
||||
debian-70rc1-x64:
|
||||
roles:
|
||||
- master
|
||||
platform: debian-7-amd64
|
||||
box : debian-70rc1-x64-vbox4210-nocm
|
||||
box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-70rc1-x64-vbox4210-nocm.box
|
||||
hypervisor : vagrant
|
||||
CONFIG:
|
||||
type: git
|
10
modules/firewall/spec/acceptance/nodesets/default.yml
Normal file
10
modules/firewall/spec/acceptance/nodesets/default.yml
Normal file
|
@ -0,0 +1,10 @@
|
|||
HOSTS:
|
||||
centos-64-x64:
|
||||
roles:
|
||||
- master
|
||||
platform: el-6-x86_64
|
||||
box : centos-64-x64-vbox4210-nocm
|
||||
box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
|
||||
hypervisor : vagrant
|
||||
CONFIG:
|
||||
type: foss
|
10
modules/firewall/spec/acceptance/nodesets/fedora-18-x64.yml
Normal file
10
modules/firewall/spec/acceptance/nodesets/fedora-18-x64.yml
Normal file
|
@ -0,0 +1,10 @@
|
|||
HOSTS:
|
||||
fedora-18-x64:
|
||||
roles:
|
||||
- master
|
||||
platform: fedora-18-x86_64
|
||||
box : fedora-18-x64-vbox4210-nocm
|
||||
box_url : http://puppet-vagrant-boxes.puppetlabs.com/fedora-18-x64-vbox4210-nocm.box
|
||||
hypervisor : vagrant
|
||||
CONFIG:
|
||||
type: git
|
10
modules/firewall/spec/acceptance/nodesets/sles-11sp1-x64.yml
Normal file
10
modules/firewall/spec/acceptance/nodesets/sles-11sp1-x64.yml
Normal file
|
@ -0,0 +1,10 @@
|
|||
HOSTS:
|
||||
sles-11sp1-x64:
|
||||
roles:
|
||||
- master
|
||||
platform: sles-11-x86_64
|
||||
box : sles-11sp1-x64-vbox4210-nocm
|
||||
box_url : http://puppet-vagrant-boxes.puppetlabs.com/sles-11sp1-x64-vbox4210-nocm.box
|
||||
hypervisor : vagrant
|
||||
CONFIG:
|
||||
type: git
|
|
@ -0,0 +1,10 @@
|
|||
HOSTS:
|
||||
ubuntu-server-10044-x64:
|
||||
roles:
|
||||
- master
|
||||
platform: ubuntu-10.04-amd64
|
||||
box : ubuntu-server-10044-x64-vbox4210-nocm
|
||||
box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-10044-x64-vbox4210-nocm.box
|
||||
hypervisor : vagrant
|
||||
CONFIG:
|
||||
type: git
|
|
@ -0,0 +1,10 @@
|
|||
HOSTS:
|
||||
ubuntu-server-12042-x64:
|
||||
roles:
|
||||
- master
|
||||
platform: ubuntu-12.04-amd64
|
||||
box : ubuntu-server-12042-x64-vbox4210-nocm
|
||||
box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box
|
||||
hypervisor : vagrant
|
||||
CONFIG:
|
||||
type: foss
|
|
@ -0,0 +1,9 @@
|
|||
HOSTS:
|
||||
ubuntu-server-1404-x64:
|
||||
roles:
|
||||
- master
|
||||
platform: ubuntu-14.04-64
|
||||
box: puppetlabs/ubuntu-14.04-64-nocm
|
||||
hypervisor : vagrant
|
||||
CONFIG:
|
||||
type: foss
|
154
modules/firewall/spec/acceptance/params_spec.rb
Normal file
154
modules/firewall/spec/acceptance/params_spec.rb
Normal file
|
@ -0,0 +1,154 @@
|
|||
require 'spec_helper_acceptance'
|
||||
|
||||
describe "param based tests:", :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
|
||||
# Takes a hash and converts it into a firewall resource
|
||||
def pp(params)
|
||||
name = params.delete('name') || '100 test'
|
||||
pm = <<-EOS
|
||||
firewall { '#{name}':
|
||||
EOS
|
||||
|
||||
params.each do |k,v|
|
||||
pm += <<-EOS
|
||||
#{k} => #{v},
|
||||
EOS
|
||||
end
|
||||
|
||||
pm += <<-EOS
|
||||
}
|
||||
EOS
|
||||
pm
|
||||
end
|
||||
|
||||
it 'test various params', :unless => (default['platform'].match(/el-5/) || fact('operatingsystem') == 'SLES') do
|
||||
iptables_flush_all_tables
|
||||
|
||||
ppm = pp({
|
||||
'table' => "'raw'",
|
||||
'socket' => 'true',
|
||||
'chain' => "'PREROUTING'",
|
||||
'jump' => 'LOG',
|
||||
'log_level' => 'debug',
|
||||
})
|
||||
|
||||
expect(apply_manifest(ppm, :catch_failures => true).exit_code).to eq(2)
|
||||
expect(apply_manifest(ppm, :catch_failures => true).exit_code).to be_zero
|
||||
end
|
||||
|
||||
it 'test log rule' do
|
||||
iptables_flush_all_tables
|
||||
|
||||
ppm = pp({
|
||||
'name' => '998 log all',
|
||||
'proto' => 'all',
|
||||
'jump' => 'LOG',
|
||||
'log_level' => 'debug',
|
||||
})
|
||||
expect(apply_manifest(ppm, :catch_failures => true).exit_code).to eq(2)
|
||||
expect(apply_manifest(ppm, :catch_failures => true).exit_code).to be_zero
|
||||
end
|
||||
|
||||
it 'test log rule - changing names' do
|
||||
iptables_flush_all_tables
|
||||
|
||||
ppm1 = pp({
|
||||
'name' => '004 log all INVALID packets',
|
||||
'chain' => 'INPUT',
|
||||
'proto' => 'all',
|
||||
'ctstate' => 'INVALID',
|
||||
'jump' => 'LOG',
|
||||
'log_level' => '3',
|
||||
'log_prefix' => '"IPTABLES dropped invalid: "',
|
||||
})
|
||||
|
||||
ppm2 = pp({
|
||||
'name' => '003 log all INVALID packets',
|
||||
'chain' => 'INPUT',
|
||||
'proto' => 'all',
|
||||
'ctstate' => 'INVALID',
|
||||
'jump' => 'LOG',
|
||||
'log_level' => '3',
|
||||
'log_prefix' => '"IPTABLES dropped invalid: "',
|
||||
})
|
||||
|
||||
expect(apply_manifest(ppm1, :catch_failures => true).exit_code).to eq(2)
|
||||
|
||||
ppm = <<-EOS + "\n" + ppm2
|
||||
resources { 'firewall':
|
||||
purge => true,
|
||||
}
|
||||
EOS
|
||||
expect(apply_manifest(ppm, :catch_failures => true).exit_code).to eq(2)
|
||||
end
|
||||
|
||||
it 'test chain - changing names' do
|
||||
iptables_flush_all_tables
|
||||
|
||||
ppm1 = pp({
|
||||
'name' => '004 with a chain',
|
||||
'chain' => 'INPUT',
|
||||
'proto' => 'all',
|
||||
})
|
||||
|
||||
ppm2 = pp({
|
||||
'name' => '004 with a chain',
|
||||
'chain' => 'OUTPUT',
|
||||
'proto' => 'all',
|
||||
})
|
||||
|
||||
apply_manifest(ppm1, :expect_changes => true)
|
||||
|
||||
ppm = <<-EOS + "\n" + ppm2
|
||||
resources { 'firewall':
|
||||
purge => true,
|
||||
}
|
||||
EOS
|
||||
expect(apply_manifest(ppm2, :expect_failures => true).stderr).to match(/is not supported/)
|
||||
end
|
||||
|
||||
it 'test log rule - idempotent' do
|
||||
iptables_flush_all_tables
|
||||
|
||||
ppm1 = pp({
|
||||
'name' => '004 log all INVALID packets',
|
||||
'chain' => 'INPUT',
|
||||
'proto' => 'all',
|
||||
'ctstate' => 'INVALID',
|
||||
'jump' => 'LOG',
|
||||
'log_level' => '3',
|
||||
'log_prefix' => '"IPTABLES dropped invalid: "',
|
||||
})
|
||||
|
||||
expect(apply_manifest(ppm1, :catch_failures => true).exit_code).to eq(2)
|
||||
expect(apply_manifest(ppm1, :catch_failures => true).exit_code).to be_zero
|
||||
end
|
||||
|
||||
it 'test src_range rule' do
|
||||
iptables_flush_all_tables
|
||||
|
||||
ppm = pp({
|
||||
'name' => '997 block src ip range',
|
||||
'chain' => 'INPUT',
|
||||
'proto' => 'all',
|
||||
'action' => 'drop',
|
||||
'src_range' => '"10.0.0.1-10.0.0.10"',
|
||||
})
|
||||
expect(apply_manifest(ppm, :catch_failures => true).exit_code).to eq(2)
|
||||
expect(apply_manifest(ppm, :catch_failures => true).exit_code).to be_zero
|
||||
end
|
||||
|
||||
it 'test dst_range rule' do
|
||||
iptables_flush_all_tables
|
||||
|
||||
ppm = pp({
|
||||
'name' => '998 block dst ip range',
|
||||
'chain' => 'INPUT',
|
||||
'proto' => 'all',
|
||||
'action' => 'drop',
|
||||
'dst_range' => '"10.0.0.2-10.0.0.20"',
|
||||
})
|
||||
expect(apply_manifest(ppm, :catch_failures => true).exit_code).to eq(2)
|
||||
expect(apply_manifest(ppm, :catch_failures => true).exit_code).to be_zero
|
||||
end
|
||||
|
||||
end
|
124
modules/firewall/spec/acceptance/purge_spec.rb
Normal file
124
modules/firewall/spec/acceptance/purge_spec.rb
Normal file
|
@ -0,0 +1,124 @@
|
|||
require 'spec_helper_acceptance'
|
||||
|
||||
describe "purge tests:", :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
|
||||
context('resources purge') do
|
||||
before(:all) do
|
||||
iptables_flush_all_tables
|
||||
|
||||
shell('iptables -A INPUT -s 1.2.1.2')
|
||||
shell('iptables -A INPUT -s 1.2.1.2')
|
||||
end
|
||||
|
||||
it 'make sure duplicate existing rules get purged' do
|
||||
|
||||
pp = <<-EOS
|
||||
class { 'firewall': }
|
||||
resources { 'firewall':
|
||||
purge => true,
|
||||
}
|
||||
EOS
|
||||
|
||||
apply_manifest(pp, :expect_changes => true)
|
||||
end
|
||||
|
||||
it 'saves' do
|
||||
shell('iptables-save') do |r|
|
||||
expect(r.stdout).to_not match(/1\.2\.1\.2/)
|
||||
expect(r.stderr).to eq("")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context('chain purge') do
|
||||
before(:each) do
|
||||
iptables_flush_all_tables
|
||||
|
||||
shell('iptables -A INPUT -p tcp -s 1.2.1.1')
|
||||
shell('iptables -A INPUT -p udp -s 1.2.1.1')
|
||||
shell('iptables -A OUTPUT -s 1.2.1.2 -m comment --comment "010 output-1.2.1.2"')
|
||||
end
|
||||
|
||||
it 'purges only the specified chain' do
|
||||
pp = <<-EOS
|
||||
class { 'firewall': }
|
||||
firewallchain { 'INPUT:filter:IPv4':
|
||||
purge => true,
|
||||
}
|
||||
EOS
|
||||
|
||||
apply_manifest(pp, :expect_changes => true)
|
||||
|
||||
shell('iptables-save') do |r|
|
||||
expect(r.stdout).to match(/010 output-1\.2\.1\.2/)
|
||||
expect(r.stdout).to_not match(/1\.2\.1\.1/)
|
||||
expect(r.stderr).to eq("")
|
||||
end
|
||||
end
|
||||
|
||||
it 'ignores managed rules' do
|
||||
pp = <<-EOS
|
||||
class { 'firewall': }
|
||||
firewallchain { 'OUTPUT:filter:IPv4':
|
||||
purge => true,
|
||||
}
|
||||
firewall { '010 output-1.2.1.2':
|
||||
chain => 'OUTPUT',
|
||||
proto => 'all',
|
||||
source => '1.2.1.2',
|
||||
}
|
||||
EOS
|
||||
|
||||
apply_manifest(pp, :catch_changes => true)
|
||||
end
|
||||
|
||||
it 'ignores specified rules' do
|
||||
pp = <<-EOS
|
||||
class { 'firewall': }
|
||||
firewallchain { 'INPUT:filter:IPv4':
|
||||
purge => true,
|
||||
ignore => [
|
||||
'-s 1\.2\.1\.1',
|
||||
],
|
||||
}
|
||||
EOS
|
||||
|
||||
apply_manifest(pp, :catch_changes => true)
|
||||
end
|
||||
|
||||
it 'adds managed rules with ignored rules' do
|
||||
pp = <<-EOS
|
||||
class { 'firewall': }
|
||||
firewallchain { 'INPUT:filter:IPv4':
|
||||
purge => true,
|
||||
ignore => [
|
||||
'-s 1\.2\.1\.1',
|
||||
],
|
||||
}
|
||||
firewall { '014 input-1.2.1.6':
|
||||
chain => 'INPUT',
|
||||
proto => 'all',
|
||||
source => '1.2.1.6',
|
||||
}
|
||||
-> firewall { '013 input-1.2.1.5':
|
||||
chain => 'INPUT',
|
||||
proto => 'all',
|
||||
source => '1.2.1.5',
|
||||
}
|
||||
-> firewall { '012 input-1.2.1.4':
|
||||
chain => 'INPUT',
|
||||
proto => 'all',
|
||||
source => '1.2.1.4',
|
||||
}
|
||||
-> firewall { '011 input-1.2.1.3':
|
||||
chain => 'INPUT',
|
||||
proto => 'all',
|
||||
source => '1.2.1.3',
|
||||
}
|
||||
EOS
|
||||
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
|
||||
expect(shell('iptables-save').stdout).to match(/-A INPUT -s 1\.2\.1\.1(\/32)? -p tcp\s?\n-A INPUT -s 1\.2\.1\.1(\/32)? -p udp/)
|
||||
end
|
||||
end
|
||||
end
|
92
modules/firewall/spec/acceptance/resource_cmd_spec.rb
Normal file
92
modules/firewall/spec/acceptance/resource_cmd_spec.rb
Normal file
|
@ -0,0 +1,92 @@
|
|||
require 'spec_helper_acceptance'
|
||||
|
||||
# Here we want to test the the resource commands ability to work with different
|
||||
# existing ruleset scenarios. This will give the parsing capabilities of the
|
||||
# code a good work out.
|
||||
describe 'puppet resource firewall command:', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
|
||||
context 'make sure it returns no errors when executed on a clean machine' do
|
||||
it do
|
||||
shell('puppet resource firewall') do |r|
|
||||
r.exit_code.should be_zero
|
||||
# don't check stdout, some boxes come with rules, that is normal
|
||||
# don't check stderr, puppet throws deprecation warnings
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'flush iptables and make sure it returns nothing afterwards' do
|
||||
before(:all) do
|
||||
iptables_flush_all_tables
|
||||
end
|
||||
|
||||
# No rules, means no output thanks. And no errors as well.
|
||||
it do
|
||||
shell('puppet resource firewall') do |r|
|
||||
r.exit_code.should be_zero
|
||||
r.stdout.should == "\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'accepts rules without comments' do
|
||||
before(:all) do
|
||||
iptables_flush_all_tables
|
||||
shell('iptables -A INPUT -j ACCEPT -p tcp --dport 80')
|
||||
end
|
||||
|
||||
it do
|
||||
shell('puppet resource firewall') do |r|
|
||||
r.exit_code.should be_zero
|
||||
# don't check stdout, testing preexisting rules, output is normal
|
||||
# don't check stderr, puppet throws deprecation warnings
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'accepts rules with invalid comments' do
|
||||
before(:all) do
|
||||
iptables_flush_all_tables
|
||||
shell('iptables -A INPUT -j ACCEPT -p tcp --dport 80 -m comment --comment "http"')
|
||||
end
|
||||
|
||||
it do
|
||||
shell('puppet resource firewall') do |r|
|
||||
r.exit_code.should be_zero
|
||||
# don't check stdout, testing preexisting rules, output is normal
|
||||
# don't check stderr, puppet throws deprecation warnings
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'accepts rules with negation' do
|
||||
before :all do
|
||||
iptables_flush_all_tables
|
||||
shell('iptables -t nat -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -p tcp -j MASQUERADE --to-ports 1024-65535')
|
||||
shell('iptables -t nat -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -p udp -j MASQUERADE --to-ports 1024-65535')
|
||||
shell('iptables -t nat -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j MASQUERADE')
|
||||
end
|
||||
|
||||
it do
|
||||
shell('puppet resource firewall') do |r|
|
||||
r.exit_code.should be_zero
|
||||
# don't check stdout, testing preexisting rules, output is normal
|
||||
# don't check stderr, puppet throws deprecation warnings
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'accepts rules with match extension tcp flag' do
|
||||
before :all do
|
||||
iptables_flush_all_tables
|
||||
shell('iptables -t mangle -A PREROUTING -d 1.2.3.4 -p tcp -m tcp -m multiport --dports 80,443,8140 -j MARK --set-mark 42')
|
||||
end
|
||||
|
||||
it do
|
||||
shell('puppet resource firewall') do |r|
|
||||
r.exit_code.should be_zero
|
||||
# don't check stdout, testing preexisting rules, output is normal
|
||||
# don't check stderr, puppet throws deprecation warnings
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
252
modules/firewall/spec/acceptance/rules_spec.rb
Normal file
252
modules/firewall/spec/acceptance/rules_spec.rb
Normal file
|
@ -0,0 +1,252 @@
|
|||
require 'spec_helper_acceptance'
|
||||
|
||||
describe 'complex ruleset 1', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
|
||||
before :all do
|
||||
iptables_flush_all_tables
|
||||
end
|
||||
|
||||
after :all do
|
||||
shell('iptables -t filter -P INPUT ACCEPT')
|
||||
shell('iptables -t filter -P FORWARD ACCEPT')
|
||||
shell('iptables -t filter -P OUTPUT ACCEPT')
|
||||
shell('iptables -t filter --flush')
|
||||
end
|
||||
|
||||
it 'applies cleanly' do
|
||||
pp = <<-EOS
|
||||
firewall { '090 forward allow local':
|
||||
chain => 'FORWARD',
|
||||
proto => 'all',
|
||||
source => '10.0.0.0/8',
|
||||
destination => '10.0.0.0/8',
|
||||
action => 'accept',
|
||||
}
|
||||
firewall { '100 forward standard allow tcp':
|
||||
chain => 'FORWARD',
|
||||
source => '10.0.0.0/8',
|
||||
destination => '!10.0.0.0/8',
|
||||
proto => 'tcp',
|
||||
state => 'NEW',
|
||||
port => [80,443,21,20,22,53,123,43,873,25,465],
|
||||
action => 'accept',
|
||||
}
|
||||
firewall { '100 forward standard allow udp':
|
||||
chain => 'FORWARD',
|
||||
source => '10.0.0.0/8',
|
||||
destination => '!10.0.0.0/8',
|
||||
proto => 'udp',
|
||||
port => [53,123],
|
||||
action => 'accept',
|
||||
}
|
||||
firewall { '100 forward standard allow icmp':
|
||||
chain => 'FORWARD',
|
||||
source => '10.0.0.0/8',
|
||||
destination => '!10.0.0.0/8',
|
||||
proto => 'icmp',
|
||||
action => 'accept',
|
||||
}
|
||||
|
||||
firewall { '090 ignore ipsec':
|
||||
table => 'nat',
|
||||
chain => 'POSTROUTING',
|
||||
outiface => 'eth0',
|
||||
ipsec_policy => 'ipsec',
|
||||
ipsec_dir => 'out',
|
||||
action => 'accept',
|
||||
}
|
||||
firewall { '093 ignore 10.0.0.0/8':
|
||||
table => 'nat',
|
||||
chain => 'POSTROUTING',
|
||||
outiface => 'eth0',
|
||||
destination => '10.0.0.0/8',
|
||||
action => 'accept',
|
||||
}
|
||||
firewall { '093 ignore 172.16.0.0/12':
|
||||
table => 'nat',
|
||||
chain => 'POSTROUTING',
|
||||
outiface => 'eth0',
|
||||
destination => '172.16.0.0/12',
|
||||
action => 'accept',
|
||||
}
|
||||
firewall { '093 ignore 192.168.0.0/16':
|
||||
table => 'nat',
|
||||
chain => 'POSTROUTING',
|
||||
outiface => 'eth0',
|
||||
destination => '192.168.0.0/16',
|
||||
action => 'accept',
|
||||
}
|
||||
firewall { '100 masq outbound':
|
||||
table => 'nat',
|
||||
chain => 'POSTROUTING',
|
||||
outiface => 'eth0',
|
||||
jump => 'MASQUERADE',
|
||||
}
|
||||
firewall { '101 redirect port 1':
|
||||
table => 'nat',
|
||||
chain => 'PREROUTING',
|
||||
iniface => 'eth0',
|
||||
proto => 'tcp',
|
||||
dport => '1',
|
||||
toports => '22',
|
||||
jump => 'REDIRECT',
|
||||
}
|
||||
EOS
|
||||
|
||||
# Run it twice and test for idempotency
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
|
||||
end
|
||||
|
||||
it 'contains appropriate rules' do
|
||||
shell('iptables-save') do |r|
|
||||
[
|
||||
/INPUT ACCEPT/,
|
||||
/FORWARD ACCEPT/,
|
||||
/OUTPUT ACCEPT/,
|
||||
/-A FORWARD -s 10.0.0.0\/(8|255\.0\.0\.0) -d 10.0.0.0\/(8|255\.0\.0\.0) -m comment --comment \"090 forward allow local\" -j ACCEPT/,
|
||||
/-A FORWARD -s 10.0.0.0\/(8|255\.0\.0\.0) (! -d|-d !) 10.0.0.0\/(8|255\.0\.0\.0) -p icmp -m comment --comment \"100 forward standard allow icmp\" -j ACCEPT/,
|
||||
/-A FORWARD -s 10.0.0.0\/(8|255\.0\.0\.0) (! -d|-d !) 10.0.0.0\/(8|255\.0\.0\.0) -p tcp -m multiport --ports 80,443,21,20,22,53,123,43,873,25,465 -m comment --comment \"100 forward standard allow tcp\" -m state --state NEW -j ACCEPT/,
|
||||
/-A FORWARD -s 10.0.0.0\/(8|255\.0\.0\.0) (! -d|-d !) 10.0.0.0\/(8|255\.0\.0\.0) -p udp -m multiport --ports 53,123 -m comment --comment \"100 forward standard allow udp\" -j ACCEPT/
|
||||
].each do |line|
|
||||
expect(r.stdout).to match(line)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'complex ruleset 2' do
|
||||
after :all do
|
||||
shell('iptables -t filter -P INPUT ACCEPT')
|
||||
shell('iptables -t filter -P FORWARD ACCEPT')
|
||||
shell('iptables -t filter -P OUTPUT ACCEPT')
|
||||
shell('iptables -t filter --flush')
|
||||
expect(shell('iptables -t filter -X LOCAL_INPUT').stderr).to eq("")
|
||||
expect(shell('iptables -t filter -X LOCAL_INPUT_PRE').stderr).to eq("")
|
||||
end
|
||||
|
||||
it 'applies cleanly' do
|
||||
pp = <<-EOS
|
||||
class { '::firewall': }
|
||||
|
||||
Firewall {
|
||||
proto => 'all',
|
||||
stage => 'pre',
|
||||
}
|
||||
Firewallchain {
|
||||
stage => 'pre',
|
||||
purge => 'true',
|
||||
ignore => [
|
||||
'--comment "[^"]*(?i:ignore)[^"]*"',
|
||||
],
|
||||
}
|
||||
|
||||
firewall { '010 INPUT allow established and related':
|
||||
proto => 'all',
|
||||
state => ['ESTABLISHED', 'RELATED'],
|
||||
action => 'accept',
|
||||
before => Firewallchain['INPUT:filter:IPv4'],
|
||||
}
|
||||
firewall { '012 accept loopback':
|
||||
iniface => 'lo',
|
||||
action => 'accept',
|
||||
before => Firewallchain['INPUT:filter:IPv4'],
|
||||
}
|
||||
firewall { '020 ssh':
|
||||
proto => 'tcp',
|
||||
dport => '22',
|
||||
state => 'NEW',
|
||||
action => 'accept',
|
||||
before => Firewallchain['INPUT:filter:IPv4'],
|
||||
}
|
||||
|
||||
firewall { '013 icmp echo-request':
|
||||
proto => 'icmp',
|
||||
icmp => 'echo-request',
|
||||
action => 'accept',
|
||||
source => '10.0.0.0/8',
|
||||
}
|
||||
firewall { '013 icmp destination-unreachable':
|
||||
proto => 'icmp',
|
||||
icmp => 'destination-unreachable',
|
||||
action => 'accept',
|
||||
}
|
||||
firewall { '013 icmp time-exceeded':
|
||||
proto => 'icmp',
|
||||
icmp => 'time-exceeded',
|
||||
action => 'accept',
|
||||
}
|
||||
firewall { '999 reject':
|
||||
action => 'reject',
|
||||
reject => 'icmp-host-prohibited',
|
||||
}
|
||||
|
||||
|
||||
firewallchain { 'LOCAL_INPUT_PRE:filter:IPv4': }
|
||||
firewall { '001 LOCAL_INPUT_PRE':
|
||||
jump => 'LOCAL_INPUT_PRE',
|
||||
require => Firewallchain['LOCAL_INPUT_PRE:filter:IPv4'],
|
||||
}
|
||||
firewallchain { 'LOCAL_INPUT:filter:IPv4': }
|
||||
firewall { '900 LOCAL_INPUT':
|
||||
jump => 'LOCAL_INPUT',
|
||||
require => Firewallchain['LOCAL_INPUT:filter:IPv4'],
|
||||
}
|
||||
firewallchain { 'INPUT:filter:IPv4':
|
||||
policy => 'drop',
|
||||
ignore => [
|
||||
'-j fail2ban-ssh',
|
||||
'--comment "[^"]*(?i:ignore)[^"]*"',
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
firewall { '010 allow established and related':
|
||||
chain => 'FORWARD',
|
||||
proto => 'all',
|
||||
state => ['ESTABLISHED','RELATED'],
|
||||
action => 'accept',
|
||||
before => Firewallchain['FORWARD:filter:IPv4'],
|
||||
}
|
||||
firewallchain { 'FORWARD:filter:IPv4':
|
||||
policy => 'drop',
|
||||
}
|
||||
|
||||
firewallchain { 'OUTPUT:filter:IPv4': }
|
||||
|
||||
|
||||
# purge unknown rules from mangle table
|
||||
firewallchain { ['PREROUTING:mangle:IPv4', 'INPUT:mangle:IPv4', 'FORWARD:mangle:IPv4', 'OUTPUT:mangle:IPv4', 'POSTROUTING:mangle:IPv4']: }
|
||||
|
||||
# and the nat table
|
||||
firewallchain { ['PREROUTING:nat:IPv4', 'INPUT:nat:IPv4', 'OUTPUT:nat:IPv4', 'POSTROUTING:nat:IPv4']: }
|
||||
EOS
|
||||
|
||||
# Run it twice and test for idempotency
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
apply_manifest(pp, :catch_changes => true)
|
||||
end
|
||||
|
||||
it 'contains appropriate rules' do
|
||||
shell('iptables-save') do |r|
|
||||
[
|
||||
/INPUT DROP/,
|
||||
/FORWARD DROP/,
|
||||
/OUTPUT ACCEPT/,
|
||||
/LOCAL_INPUT/,
|
||||
/LOCAL_INPUT_PRE/,
|
||||
/-A INPUT -m comment --comment \"001 LOCAL_INPUT_PRE\" -j LOCAL_INPUT_PRE/,
|
||||
/-A INPUT -m comment --comment \"010 INPUT allow established and related\" -m state --state RELATED,ESTABLISHED -j ACCEPT/,
|
||||
/-A INPUT -i lo -m comment --comment \"012 accept loopback\" -j ACCEPT/,
|
||||
/-A INPUT -p icmp -m comment --comment \"013 icmp destination-unreachable\" -m icmp --icmp-type 3 -j ACCEPT/,
|
||||
/-A INPUT -s 10.0.0.0\/(8|255\.0\.0\.0) -p icmp -m comment --comment \"013 icmp echo-request\" -m icmp --icmp-type 8 -j ACCEPT/,
|
||||
/-A INPUT -p icmp -m comment --comment \"013 icmp time-exceeded\" -m icmp --icmp-type 11 -j ACCEPT/,
|
||||
/-A INPUT -p tcp -m multiport --dports 22 -m comment --comment \"020 ssh\" -m state --state NEW -j ACCEPT/,
|
||||
/-A INPUT -m comment --comment \"900 LOCAL_INPUT\" -j LOCAL_INPUT/,
|
||||
/-A INPUT -m comment --comment \"999 reject\" -j REJECT --reject-with icmp-host-prohibited/,
|
||||
/-A FORWARD -m comment --comment \"010 allow established and related\" -m state --state RELATED,ESTABLISHED -j ACCEPT/
|
||||
].each do |line|
|
||||
expect(r.stdout).to match(line)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
97
modules/firewall/spec/acceptance/socket_spec.rb
Normal file
97
modules/firewall/spec/acceptance/socket_spec.rb
Normal file
|
@ -0,0 +1,97 @@
|
|||
require 'spec_helper_acceptance'
|
||||
|
||||
# RHEL5 does not support -m socket
|
||||
describe 'firewall socket property', :unless => (UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) || default['platform'] =~ /el-5/ || fact('operatingsystem') == 'SLES') do
|
||||
before :all do
|
||||
iptables_flush_all_tables
|
||||
end
|
||||
|
||||
shared_examples "is idempotent" do |value, line_match|
|
||||
it "changes the value to #{value}" do
|
||||
pp = <<-EOS
|
||||
class { '::firewall': }
|
||||
firewall { '598 - test':
|
||||
ensure => present,
|
||||
proto => 'tcp',
|
||||
chain => 'PREROUTING',
|
||||
table => 'raw',
|
||||
#{value}
|
||||
}
|
||||
EOS
|
||||
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
apply_manifest(pp, :catch_changes => true)
|
||||
|
||||
shell('iptables-save -t raw') do |r|
|
||||
expect(r.stdout).to match(/#{line_match}/)
|
||||
end
|
||||
end
|
||||
end
|
||||
shared_examples "doesn't change" do |value, line_match|
|
||||
it "doesn't change the value to #{value}" do
|
||||
pp = <<-EOS
|
||||
class { '::firewall': }
|
||||
firewall { '598 - test':
|
||||
ensure => present,
|
||||
proto => 'tcp',
|
||||
chain => 'PREROUTING',
|
||||
table => 'raw',
|
||||
#{value}
|
||||
}
|
||||
EOS
|
||||
|
||||
apply_manifest(pp, :catch_changes => true)
|
||||
|
||||
shell('iptables-save -t raw') do |r|
|
||||
expect(r.stdout).to match(/#{line_match}/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'adding a rule' do
|
||||
context 'when unset' do
|
||||
before :all do
|
||||
iptables_flush_all_tables
|
||||
end
|
||||
it_behaves_like 'is idempotent', '', /-A PREROUTING -p tcp -m comment --comment "598 - test"/
|
||||
end
|
||||
context 'when set to true' do
|
||||
before :all do
|
||||
iptables_flush_all_tables
|
||||
end
|
||||
it_behaves_like 'is idempotent', 'socket => true,', /-A PREROUTING -p tcp -m socket -m comment --comment "598 - test"/
|
||||
end
|
||||
context 'when set to false' do
|
||||
before :all do
|
||||
iptables_flush_all_tables
|
||||
end
|
||||
it_behaves_like "is idempotent", 'socket => false,', /-A PREROUTING -p tcp -m comment --comment "598 - test"/
|
||||
end
|
||||
end
|
||||
describe 'editing a rule' do
|
||||
context 'when unset or false' do
|
||||
before :each do
|
||||
iptables_flush_all_tables
|
||||
shell('iptables -t raw -A PREROUTING -p tcp -m comment --comment "598 - test"')
|
||||
end
|
||||
context 'and current value is false' do
|
||||
it_behaves_like "doesn't change", 'socket => false,', /-A PREROUTING -p tcp -m comment --comment "598 - test"/
|
||||
end
|
||||
context 'and current value is true' do
|
||||
it_behaves_like "is idempotent", 'socket => true,', /-A PREROUTING -p tcp -m socket -m comment --comment "598 - test"/
|
||||
end
|
||||
end
|
||||
context 'when set to true' do
|
||||
before :each do
|
||||
iptables_flush_all_tables
|
||||
shell('iptables -t raw -A PREROUTING -p tcp -m socket -m comment --comment "598 - test"')
|
||||
end
|
||||
context 'and current value is false' do
|
||||
it_behaves_like "is idempotent", 'socket => false,', /-A PREROUTING -p tcp -m comment --comment "598 - test"/
|
||||
end
|
||||
context 'and current value is true' do
|
||||
it_behaves_like "doesn't change", 'socket => true,', /-A PREROUTING -p tcp -m socket -m comment --comment "598 - test"/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
55
modules/firewall/spec/acceptance/standard_usage_spec.rb
Normal file
55
modules/firewall/spec/acceptance/standard_usage_spec.rb
Normal file
|
@ -0,0 +1,55 @@
|
|||
require 'spec_helper_acceptance'
|
||||
|
||||
# Some tests for the standard recommended usage
|
||||
describe 'standard usage tests:', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
|
||||
it 'applies twice' do
|
||||
pp = <<-EOS
|
||||
class my_fw::pre {
|
||||
Firewall {
|
||||
require => undef,
|
||||
}
|
||||
|
||||
# Default firewall rules
|
||||
firewall { '000 accept all icmp':
|
||||
proto => 'icmp',
|
||||
action => 'accept',
|
||||
}->
|
||||
firewall { '001 accept all to lo interface':
|
||||
proto => 'all',
|
||||
iniface => 'lo',
|
||||
action => 'accept',
|
||||
}->
|
||||
firewall { '002 accept related established rules':
|
||||
proto => 'all',
|
||||
ctstate => ['RELATED', 'ESTABLISHED'],
|
||||
action => 'accept',
|
||||
}
|
||||
}
|
||||
class my_fw::post {
|
||||
firewall { '999 drop all':
|
||||
proto => 'all',
|
||||
action => 'drop',
|
||||
before => undef,
|
||||
}
|
||||
}
|
||||
resources { "firewall":
|
||||
purge => true
|
||||
}
|
||||
Firewall {
|
||||
before => Class['my_fw::post'],
|
||||
require => Class['my_fw::pre'],
|
||||
}
|
||||
class { ['my_fw::pre', 'my_fw::post']: }
|
||||
class { 'firewall': }
|
||||
firewall { '500 open up port 22':
|
||||
action => 'accept',
|
||||
proto => 'tcp',
|
||||
dport => 22,
|
||||
}
|
||||
EOS
|
||||
|
||||
# Run it twice and test for idempotency
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
|
||||
end
|
||||
end
|
10
modules/firewall/spec/acceptance/unsupported_spec.rb
Normal file
10
modules/firewall/spec/acceptance/unsupported_spec.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
require 'spec_helper_acceptance'
|
||||
|
||||
describe 'unsupported distributions and OSes', :if => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
|
||||
it 'should fail' do
|
||||
pp = <<-EOS
|
||||
class { 'firewall': }
|
||||
EOS
|
||||
expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/not currently supported/i)
|
||||
end
|
||||
end
|
107
modules/firewall/spec/fixtures/ip6tables/conversion_hash.rb
vendored
Normal file
107
modules/firewall/spec/fixtures/ip6tables/conversion_hash.rb
vendored
Normal file
|
@ -0,0 +1,107 @@
|
|||
# These hashes allow us to iterate across a series of test data
|
||||
# creating rspec examples for each parameter to ensure the input :line
|
||||
# extrapolates to the desired value for the parameter in question. And
|
||||
# vice-versa
|
||||
|
||||
# This hash is for testing a line conversion to a hash of parameters
|
||||
# which will be used to create a resource.
|
||||
ARGS_TO_HASH6 = {
|
||||
'source_destination_ipv6_no_cidr' => {
|
||||
:line => '-A INPUT -s 2001:db8:85a3::8a2e:370:7334 -d 2001:db8:85a3::8a2e:370:7334 -m comment --comment "000 source destination ipv6 no cidr"',
|
||||
:table => 'filter',
|
||||
:provider => 'ip6tables',
|
||||
:params => {
|
||||
:source => '2001:db8:85a3::8a2e:370:7334/128',
|
||||
:destination => '2001:db8:85a3::8a2e:370:7334/128',
|
||||
},
|
||||
},
|
||||
'source_destination_ipv6_netmask' => {
|
||||
:line => '-A INPUT -s 2001:db8:1234::/ffff:ffff:ffff:0000:0000:0000:0000:0000 -d 2001:db8:4321::/ffff:ffff:ffff:0000:0000:0000:0000:0000 -m comment --comment "000 source destination ipv6 netmask"',
|
||||
:table => 'filter',
|
||||
:provider => 'ip6tables',
|
||||
:params => {
|
||||
:source => '2001:db8:1234::/48',
|
||||
:destination => '2001:db8:4321::/48',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
# This hash is for testing converting a hash to an argument line.
|
||||
HASH_TO_ARGS6 = {
|
||||
'zero_prefixlen_ipv6' => {
|
||||
:params => {
|
||||
:name => '100 zero prefix length ipv6',
|
||||
:table => 'filter',
|
||||
:provider => 'ip6tables',
|
||||
:source => '::/0',
|
||||
:destination => '::/0',
|
||||
},
|
||||
:args => ['-t', :filter, '-p', :tcp, '-m', 'comment', '--comment', '100 zero prefix length ipv6'],
|
||||
},
|
||||
'source_destination_ipv4_no_cidr' => {
|
||||
:params => {
|
||||
:name => '000 source destination ipv4 no cidr',
|
||||
:table => 'filter',
|
||||
:provider => 'ip6tables',
|
||||
:source => '1.1.1.1',
|
||||
:destination => '2.2.2.2',
|
||||
},
|
||||
:args => ['-t', :filter, '-s', '1.1.1.1/32', '-d', '2.2.2.2/32', '-p', :tcp, '-m', 'comment', '--comment', '000 source destination ipv4 no cidr'],
|
||||
},
|
||||
'source_destination_ipv6_no_cidr' => {
|
||||
:params => {
|
||||
:name => '000 source destination ipv6 no cidr',
|
||||
:table => 'filter',
|
||||
:provider => 'ip6tables',
|
||||
:source => '2001:db8:1234::',
|
||||
:destination => '2001:db8:4321::',
|
||||
},
|
||||
:args => ['-t', :filter, '-s', '2001:db8:1234::/128', '-d', '2001:db8:4321::/128', '-p', :tcp, '-m', 'comment', '--comment', '000 source destination ipv6 no cidr'],
|
||||
},
|
||||
'source_destination_ipv6_netmask' => {
|
||||
:params => {
|
||||
:name => '000 source destination ipv6 netmask',
|
||||
:table => 'filter',
|
||||
:provider => 'ip6tables',
|
||||
:source => '2001:db8:1234::/ffff:ffff:ffff:0000:0000:0000:0000:0000',
|
||||
:destination => '2001:db8:4321::/ffff:ffff:ffff:0000:0000:0000:0000:0000',
|
||||
},
|
||||
:args => ['-t', :filter, '-s', '2001:db8:1234::/48', '-d', '2001:db8:4321::/48', '-p', :tcp, '-m', 'comment', '--comment', '000 source destination ipv6 netmask'],
|
||||
},
|
||||
'frag_ishasmorefrags' => {
|
||||
:params => {
|
||||
:name => "100 has more fragments",
|
||||
:ishasmorefrags => true,
|
||||
:provider => 'ip6tables',
|
||||
:table => "filter",
|
||||
},
|
||||
:args => ["-t", :filter, "-p", :tcp, "-m", "frag", "--fragid", "0", "--fragmore", "-m", "comment", "--comment", "100 has more fragments"],
|
||||
},
|
||||
'frag_islastfrag' => {
|
||||
:params => {
|
||||
:name => "100 last fragment",
|
||||
:islastfrag => true,
|
||||
:provider => 'ip6tables',
|
||||
:table => "filter",
|
||||
},
|
||||
:args => ["-t", :filter, "-p", :tcp, "-m", "frag", "--fragid", "0", "--fraglast", "-m", "comment", "--comment", "100 last fragment"],
|
||||
},
|
||||
'frag_isfirstfrags' => {
|
||||
:params => {
|
||||
:name => "100 first fragment",
|
||||
:isfirstfrag => true,
|
||||
:provider => 'ip6tables',
|
||||
:table => "filter",
|
||||
},
|
||||
:args => ["-t", :filter, "-p", :tcp, "-m", "frag", "--fragid", "0", "--fragfirst", "-m", "comment", "--comment", "100 first fragment"],
|
||||
},
|
||||
'hop_limit' => {
|
||||
:params => {
|
||||
:name => "100 hop limit",
|
||||
:hop_limit => 255,
|
||||
:provider => 'ip6tables',
|
||||
:table => "filter",
|
||||
},
|
||||
:args => ["-t", :filter, "-p", :tcp, "-m", "comment", "--comment", "100 hop limit", "-m", "hl", "--hl-eq", 255],
|
||||
},
|
||||
}
|
934
modules/firewall/spec/fixtures/iptables/conversion_hash.rb
vendored
Normal file
934
modules/firewall/spec/fixtures/iptables/conversion_hash.rb
vendored
Normal file
|
@ -0,0 +1,934 @@
|
|||
# These hashes allow us to iterate across a series of test data
|
||||
# creating rspec examples for each parameter to ensure the input :line
|
||||
# extrapolates to the desired value for the parameter in question. And
|
||||
# vice-versa
|
||||
|
||||
# This hash is for testing a line conversion to a hash of parameters
|
||||
# which will be used to create a resource.
|
||||
ARGS_TO_HASH = {
|
||||
'dport_and_sport' => {
|
||||
:line => '-A nova-compute-FORWARD -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp --sport 68 --dport 67 -j ACCEPT',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:action => 'accept',
|
||||
:chain => 'nova-compute-FORWARD',
|
||||
:source => '0.0.0.0/32',
|
||||
:destination => '255.255.255.255/32',
|
||||
:sport => ['68'],
|
||||
:dport => ['67'],
|
||||
:proto => 'udp',
|
||||
},
|
||||
},
|
||||
'long_rule_1' => {
|
||||
: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 -m comment --comment "000 allow foo" -j ACCEPT',
|
||||
:table => 'filter',
|
||||
:compare_all => true,
|
||||
:params => {
|
||||
:action => "accept",
|
||||
:chain => "INPUT",
|
||||
:destination => "1.1.1.1/32",
|
||||
: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 -m comment --comment "000 allow foo" -j ACCEPT',
|
||||
:name => "000 allow foo",
|
||||
:proto => "tcp",
|
||||
:provider => "iptables",
|
||||
:source => "1.1.1.1/32",
|
||||
:sport => ["7061","7062"],
|
||||
:table => "filter",
|
||||
},
|
||||
},
|
||||
'action_drop_1' => {
|
||||
:line => '-A INPUT -m comment --comment "000 allow foo" -j DROP',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:jump => nil,
|
||||
:action => "drop",
|
||||
},
|
||||
},
|
||||
'action_reject_1' => {
|
||||
:line => '-A INPUT -m comment --comment "000 allow foo" -j REJECT',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:jump => nil,
|
||||
:action => "reject",
|
||||
},
|
||||
},
|
||||
'action_nil_1' => {
|
||||
:line => '-A INPUT -m comment --comment "000 allow foo"',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:jump => nil,
|
||||
:action => nil,
|
||||
},
|
||||
},
|
||||
'jump_custom_chain_1' => {
|
||||
:line => '-A INPUT -m comment --comment "000 allow foo" -j custom_chain',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:jump => "custom_chain",
|
||||
:action => nil,
|
||||
},
|
||||
},
|
||||
'source_destination_ipv4_no_cidr' => {
|
||||
:line => '-A INPUT -s 1.1.1.1 -d 2.2.2.2 -m comment --comment "000 source destination ipv4 no cidr"',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:source => '1.1.1.1/32',
|
||||
:destination => '2.2.2.2/32',
|
||||
},
|
||||
},
|
||||
'source_destination_ipv6_no_cidr' => {
|
||||
:line => '-A INPUT -s 2001:db8:85a3::8a2e:370:7334 -d 2001:db8:85a3::8a2e:370:7334 -m comment --comment "000 source destination ipv6 no cidr"',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:source => '2001:db8:85a3::8a2e:370:7334/128',
|
||||
:destination => '2001:db8:85a3::8a2e:370:7334/128',
|
||||
},
|
||||
},
|
||||
'source_destination_ipv4_netmask' => {
|
||||
:line => '-A INPUT -s 1.1.1.0/255.255.255.0 -d 2.2.0.0/255.255.0.0 -m comment --comment "000 source destination ipv4 netmask"',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:source => '1.1.1.0/24',
|
||||
:destination => '2.2.0.0/16',
|
||||
},
|
||||
},
|
||||
'source_destination_ipv6_netmask' => {
|
||||
:line => '-A INPUT -s 2001:db8:1234::/ffff:ffff:ffff:0000:0000:0000:0000:0000 -d 2001:db8:4321::/ffff:ffff:ffff:0000:0000:0000:0000:0000 -m comment --comment "000 source destination ipv6 netmask"',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:source => '2001:db8:1234::/48',
|
||||
:destination => '2001:db8:4321::/48',
|
||||
},
|
||||
},
|
||||
'source_destination_negate_source' => {
|
||||
:line => '-A INPUT ! -s 1.1.1.1 -d 2.2.2.2 -m comment --comment "000 negated source address"',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:source => '! 1.1.1.1/32',
|
||||
:destination => '2.2.2.2/32',
|
||||
},
|
||||
},
|
||||
'source_destination_negate_destination' => {
|
||||
:line => '-A INPUT -s 1.1.1.1 ! -d 2.2.2.2 -m comment --comment "000 negated destination address"',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:source => '1.1.1.1/32',
|
||||
:destination => '! 2.2.2.2/32',
|
||||
},
|
||||
},
|
||||
'source_destination_negate_destination_alternative' => {
|
||||
:line => '-A INPUT -s 1.1.1.1 -d ! 2.2.2.2 -m comment --comment "000 negated destination address alternative"',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:source => '1.1.1.1/32',
|
||||
:destination => '! 2.2.2.2/32',
|
||||
},
|
||||
},
|
||||
'dport_range_1' => {
|
||||
:line => '-A INPUT -m multiport --dports 1:1024 -m comment --comment "000 allow foo"',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:dport => ["1-1024"],
|
||||
},
|
||||
},
|
||||
'dport_range_2' => {
|
||||
:line => '-A INPUT -m multiport --dports 15,512:1024 -m comment --comment "000 allow foo"',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:dport => ["15","512-1024"],
|
||||
},
|
||||
},
|
||||
'sport_range_1' => {
|
||||
:line => '-A INPUT -m multiport --sports 1:1024 -m comment --comment "000 allow foo"',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:sport => ["1-1024"],
|
||||
},
|
||||
},
|
||||
'sport_range_2' => {
|
||||
:line => '-A INPUT -m multiport --sports 15,512:1024 -m comment --comment "000 allow foo"',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:sport => ["15","512-1024"],
|
||||
},
|
||||
},
|
||||
'dst_type_1' => {
|
||||
:line => '-A INPUT -m addrtype --dst-type LOCAL',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:dst_type => 'LOCAL',
|
||||
},
|
||||
},
|
||||
'src_type_1' => {
|
||||
:line => '-A INPUT -m addrtype --src-type LOCAL',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:src_type => 'LOCAL',
|
||||
},
|
||||
},
|
||||
'dst_range_1' => {
|
||||
:line => '-A INPUT -m iprange --dst-range 10.0.0.2-10.0.0.20',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:dst_range => '10.0.0.2-10.0.0.20',
|
||||
},
|
||||
},
|
||||
'src_range_1' => {
|
||||
:line => '-A INPUT -m iprange --src-range 10.0.0.2-10.0.0.20',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:src_range => '10.0.0.2-10.0.0.20',
|
||||
},
|
||||
},
|
||||
'tcp_flags_1' => {
|
||||
:line => '-A INPUT -p tcp -m tcp --tcp-flags SYN,RST,ACK,FIN SYN -m comment --comment "000 initiation"',
|
||||
:table => 'filter',
|
||||
:compare_all => true,
|
||||
:chain => 'INPUT',
|
||||
:proto => 'tcp',
|
||||
:params => {
|
||||
:chain => "INPUT",
|
||||
:ensure => :present,
|
||||
:line => '-A INPUT -p tcp -m tcp --tcp-flags SYN,RST,ACK,FIN SYN -m comment --comment "000 initiation"',
|
||||
:name => "000 initiation",
|
||||
:proto => "tcp",
|
||||
:provider => "iptables",
|
||||
:table => "filter",
|
||||
:tcp_flags => "SYN,RST,ACK,FIN SYN",
|
||||
},
|
||||
},
|
||||
'state_returns_sorted_values' => {
|
||||
:line => '-A INPUT -m state --state INVALID,RELATED,ESTABLISHED',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:state => ['ESTABLISHED', 'INVALID', 'RELATED'],
|
||||
:action => nil,
|
||||
},
|
||||
},
|
||||
'ctstate_returns_sorted_values' => {
|
||||
:line => '-A INPUT -m conntrack --ctstate INVALID,RELATED,ESTABLISHED',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:ctstate => ['ESTABLISHED', 'INVALID', 'RELATED'],
|
||||
:action => nil,
|
||||
},
|
||||
},
|
||||
'comment_string_character_validation' => {
|
||||
:line => '-A INPUT -s 192.168.0.1/32 -m comment --comment "000 allow from 192.168.0.1, please"',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:source => '192.168.0.1/32',
|
||||
},
|
||||
},
|
||||
'log_level_debug' => {
|
||||
:line => '-A INPUT -m comment --comment "956 INPUT log-level" -m state --state NEW -j LOG --log-level 7',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:state => ['NEW'],
|
||||
:log_level => '7',
|
||||
:jump => 'LOG'
|
||||
},
|
||||
},
|
||||
'log_level_warn' => {
|
||||
:line => '-A INPUT -m comment --comment "956 INPUT log-level" -m state --state NEW -j LOG',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:state => ['NEW'],
|
||||
:log_level => '4',
|
||||
:jump => 'LOG'
|
||||
},
|
||||
},
|
||||
'load_limit_module_and_implicit_burst' => {
|
||||
:line => '-A INPUT -m multiport --dports 123 -m comment --comment "057 INPUT limit NTP" -m limit --limit 15/hour',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:dport => ['123'],
|
||||
:limit => '15/hour',
|
||||
:burst => '5'
|
||||
},
|
||||
},
|
||||
'limit_with_explicit_burst' => {
|
||||
:line => '-A INPUT -m multiport --dports 123 -m comment --comment "057 INPUT limit NTP" -m limit --limit 30/hour --limit-burst 10',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:dport => ['123'],
|
||||
:limit => '30/hour',
|
||||
:burst => '10'
|
||||
},
|
||||
},
|
||||
'proto_ipencap' => {
|
||||
:line => '-A INPUT -p ipencap -m comment --comment "0100 INPUT accept ipencap"',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:proto => 'ipencap',
|
||||
}
|
||||
},
|
||||
'load_uid_owner_filter_module' => {
|
||||
:line => '-A OUTPUT -m owner --uid-owner root -m comment --comment "057 OUTPUT uid root only" -j ACCEPT',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:action => 'accept',
|
||||
:uid => 'root',
|
||||
:chain => 'OUTPUT',
|
||||
},
|
||||
},
|
||||
'load_uid_owner_postrouting_module' => {
|
||||
:line => '-t mangle -A POSTROUTING -m owner --uid-owner root -m comment --comment "057 POSTROUTING uid root only" -j ACCEPT',
|
||||
:table => 'mangle',
|
||||
:params => {
|
||||
:action => 'accept',
|
||||
:chain => 'POSTROUTING',
|
||||
:uid => 'root',
|
||||
},
|
||||
},
|
||||
'load_gid_owner_filter_module' => {
|
||||
:line => '-A OUTPUT -m owner --gid-owner root -m comment --comment "057 OUTPUT gid root only" -j ACCEPT',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:action => 'accept',
|
||||
:chain => 'OUTPUT',
|
||||
:gid => 'root',
|
||||
},
|
||||
},
|
||||
'load_gid_owner_postrouting_module' => {
|
||||
:line => '-t mangle -A POSTROUTING -m owner --gid-owner root -m comment --comment "057 POSTROUTING gid root only" -j ACCEPT',
|
||||
:table => 'mangle',
|
||||
:params => {
|
||||
:action => 'accept',
|
||||
:chain => 'POSTROUTING',
|
||||
:gid => 'root',
|
||||
},
|
||||
},
|
||||
'mark_set-mark' => {
|
||||
:line => '-t mangle -A PREROUTING -j MARK --set-xmark 0x3e8/0xffffffff',
|
||||
:table => 'mangle',
|
||||
:params => {
|
||||
:jump => 'MARK',
|
||||
:chain => 'PREROUTING',
|
||||
:set_mark => '0x3e8/0xffffffff',
|
||||
}
|
||||
},
|
||||
'iniface_1' => {
|
||||
:line => '-A INPUT -i eth0 -m comment --comment "060 iniface" -j DROP',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:action => 'drop',
|
||||
:chain => 'INPUT',
|
||||
:iniface => 'eth0',
|
||||
},
|
||||
},
|
||||
'iniface_with_vlans_1' => {
|
||||
:line => '-A INPUT -i eth0.234 -m comment --comment "060 iniface" -j DROP',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:action => 'drop',
|
||||
:chain => 'INPUT',
|
||||
:iniface => 'eth0.234',
|
||||
},
|
||||
},
|
||||
'iniface_with_plus_1' => {
|
||||
:line => '-A INPUT -i eth+ -m comment --comment "060 iniface" -j DROP',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:action => 'drop',
|
||||
:chain => 'INPUT',
|
||||
:iniface => 'eth+',
|
||||
},
|
||||
},
|
||||
'outiface_1' => {
|
||||
:line => '-A OUTPUT -o eth0 -m comment --comment "060 outiface" -j DROP',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:action => 'drop',
|
||||
:chain => 'OUTPUT',
|
||||
:outiface => 'eth0',
|
||||
},
|
||||
},
|
||||
'outiface_with_vlans_1' => {
|
||||
:line => '-A OUTPUT -o eth0.234 -m comment --comment "060 outiface" -j DROP',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:action => 'drop',
|
||||
:chain => 'OUTPUT',
|
||||
:outiface => 'eth0.234',
|
||||
},
|
||||
},
|
||||
'outiface_with_plus_1' => {
|
||||
:line => '-A OUTPUT -o eth+ -m comment --comment "060 outiface" -j DROP',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:action => 'drop',
|
||||
:chain => 'OUTPUT',
|
||||
:outiface => 'eth+',
|
||||
},
|
||||
},
|
||||
'pkttype multicast' => {
|
||||
:line => '-A INPUT -m pkttype --pkt-type multicast -j ACCEPT',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:action => 'accept',
|
||||
:pkttype => 'multicast',
|
||||
},
|
||||
},
|
||||
'socket_option' => {
|
||||
:line => '-A PREROUTING -m socket -j ACCEPT',
|
||||
:table => 'mangle',
|
||||
:params => {
|
||||
:action => 'accept',
|
||||
:chain => 'PREROUTING',
|
||||
:socket => true,
|
||||
},
|
||||
},
|
||||
'isfragment_option' => {
|
||||
:line => '-A INPUT -f -m comment --comment "010 a-f comment with dashf" -j ACCEPT',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:name => '010 a-f comment with dashf',
|
||||
:action => 'accept',
|
||||
:isfragment => true,
|
||||
},
|
||||
},
|
||||
'single_tcp_sport' => {
|
||||
:line => '-A OUTPUT -s 10.94.100.46/32 -p tcp -m tcp --sport 20443 -j ACCEPT',
|
||||
:table => 'mangle',
|
||||
:params => {
|
||||
:action => 'accept',
|
||||
:chain => 'OUTPUT',
|
||||
:source => "10.94.100.46/32",
|
||||
:proto => "tcp",
|
||||
:sport => ["20443"],
|
||||
},
|
||||
},
|
||||
'single_udp_sport' => {
|
||||
:line => '-A OUTPUT -s 10.94.100.46/32 -p udp -m udp --sport 20443 -j ACCEPT',
|
||||
:table => 'mangle',
|
||||
:params => {
|
||||
:action => 'accept',
|
||||
:chain => 'OUTPUT',
|
||||
:source => "10.94.100.46/32",
|
||||
:proto => "udp",
|
||||
:sport => ["20443"],
|
||||
},
|
||||
},
|
||||
'single_tcp_dport' => {
|
||||
:line => '-A OUTPUT -s 10.94.100.46/32 -p tcp -m tcp --dport 20443 -j ACCEPT',
|
||||
:table => 'mangle',
|
||||
:params => {
|
||||
:action => 'accept',
|
||||
:chain => 'OUTPUT',
|
||||
:source => "10.94.100.46/32",
|
||||
:proto => "tcp",
|
||||
:dport => ["20443"],
|
||||
},
|
||||
},
|
||||
'single_udp_dport' => {
|
||||
:line => '-A OUTPUT -s 10.94.100.46/32 -p udp -m udp --dport 20443 -j ACCEPT',
|
||||
:table => 'mangle',
|
||||
:params => {
|
||||
:action => 'accept',
|
||||
:chain => 'OUTPUT',
|
||||
:source => "10.94.100.46/32",
|
||||
:proto => "udp",
|
||||
:dport => ["20443"],
|
||||
},
|
||||
},
|
||||
'connlimit_above' => {
|
||||
:line => '-A INPUT -p tcp -m multiport --dports 22 -m comment --comment "061 REJECT connlimit_above 10" -m connlimit --connlimit-above 10 --connlimit-mask 32 -j REJECT --reject-with icmp-port-unreachable',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:proto => 'tcp',
|
||||
:dport => ["22"],
|
||||
:connlimit_above => '10',
|
||||
:action => 'reject',
|
||||
},
|
||||
},
|
||||
'connlimit_above_with_connlimit_mask' => {
|
||||
:line => '-A INPUT -p tcp -m multiport --dports 22 -m comment --comment "061 REJECT connlimit_above 10 with mask 24" -m connlimit --connlimit-above 10 --connlimit-mask 24 -j REJECT --reject-with icmp-port-unreachable',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:proto => 'tcp',
|
||||
:dport => ["22"],
|
||||
:connlimit_above => '10',
|
||||
:connlimit_mask => '24',
|
||||
:action => 'reject',
|
||||
},
|
||||
},
|
||||
'connmark' => {
|
||||
:line => '-A INPUT -m comment --comment "062 REJECT connmark" -m connmark --mark 0x1 -j REJECT --reject-with icmp-port-unreachable',
|
||||
:table => 'filter',
|
||||
:params => {
|
||||
:proto => 'all',
|
||||
:connmark => '0x1',
|
||||
:action => 'reject',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
# This hash is for testing converting a hash to an argument line.
|
||||
HASH_TO_ARGS = {
|
||||
'long_rule_1' => {
|
||||
:params => {
|
||||
:action => "accept",
|
||||
:chain => "INPUT",
|
||||
:destination => "1.1.1.1",
|
||||
:dport => ["7061","7062"],
|
||||
:ensure => :present,
|
||||
:name => "000 allow foo",
|
||||
:proto => "tcp",
|
||||
:source => "1.1.1.1",
|
||||
: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", "-m", "comment", "--comment", "000 allow foo", "-j", "ACCEPT"],
|
||||
},
|
||||
'long_rule_2' => {
|
||||
:params => {
|
||||
:chain => "INPUT",
|
||||
:destination => "2.10.13.3/24",
|
||||
:dport => ["7061"],
|
||||
:ensure => :present,
|
||||
:jump => "my_custom_chain",
|
||||
:name => "700 allow bar",
|
||||
:proto => "udp",
|
||||
:source => "1.1.1.1",
|
||||
: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", "-m", "comment", "--comment", "700 allow bar", "-j", "my_custom_chain"],
|
||||
},
|
||||
'no_action' => {
|
||||
:params => {
|
||||
:name => "100 no action",
|
||||
:table => "filter",
|
||||
},
|
||||
:args => ["-t", :filter, "-p", :tcp, "-m", "comment", "--comment",
|
||||
"100 no action"],
|
||||
},
|
||||
'zero_prefixlen_ipv4' => {
|
||||
:params => {
|
||||
:name => '100 zero prefix length ipv4',
|
||||
:table => 'filter',
|
||||
:source => '0.0.0.0/0',
|
||||
:destination => '0.0.0.0/0',
|
||||
},
|
||||
:args => ['-t', :filter, '-p', :tcp, '-m', 'comment', '--comment', '100 zero prefix length ipv4'],
|
||||
},
|
||||
'zero_prefixlen_ipv6' => {
|
||||
:params => {
|
||||
:name => '100 zero prefix length ipv6',
|
||||
:table => 'filter',
|
||||
:source => '::/0',
|
||||
:destination => '::/0',
|
||||
},
|
||||
:args => ['-t', :filter, '-p', :tcp, '-m', 'comment', '--comment', '100 zero prefix length ipv6'],
|
||||
},
|
||||
'source_destination_ipv4_no_cidr' => {
|
||||
:params => {
|
||||
:name => '000 source destination ipv4 no cidr',
|
||||
:table => 'filter',
|
||||
:source => '1.1.1.1',
|
||||
:destination => '2.2.2.2',
|
||||
},
|
||||
:args => ['-t', :filter, '-s', '1.1.1.1/32', '-d', '2.2.2.2/32', '-p', :tcp, '-m', 'comment', '--comment', '000 source destination ipv4 no cidr'],
|
||||
},
|
||||
'source_destination_ipv6_no_cidr' => {
|
||||
:params => {
|
||||
:name => '000 source destination ipv6 no cidr',
|
||||
:table => 'filter',
|
||||
:source => '2001:db8:1234::',
|
||||
:destination => '2001:db8:4321::',
|
||||
},
|
||||
:args => ['-t', :filter, '-s', '2001:db8:1234::/128', '-d', '2001:db8:4321::/128', '-p', :tcp, '-m', 'comment', '--comment', '000 source destination ipv6 no cidr'],
|
||||
},
|
||||
'source_destination_ipv4_netmask' => {
|
||||
:params => {
|
||||
:name => '000 source destination ipv4 netmask',
|
||||
:table => 'filter',
|
||||
:source => '1.1.1.0/255.255.255.0',
|
||||
:destination => '2.2.0.0/255.255.0.0',
|
||||
},
|
||||
:args => ['-t', :filter, '-s', '1.1.1.0/24', '-d', '2.2.0.0/16', '-p', :tcp, '-m', 'comment', '--comment', '000 source destination ipv4 netmask'],
|
||||
},
|
||||
'source_destination_ipv6_netmask' => {
|
||||
:params => {
|
||||
:name => '000 source destination ipv6 netmask',
|
||||
:table => 'filter',
|
||||
:source => '2001:db8:1234::/ffff:ffff:ffff:0000:0000:0000:0000:0000',
|
||||
:destination => '2001:db8:4321::/ffff:ffff:ffff:0000:0000:0000:0000:0000',
|
||||
},
|
||||
:args => ['-t', :filter, '-s', '2001:db8:1234::/48', '-d', '2001:db8:4321::/48', '-p', :tcp, '-m', 'comment', '--comment', '000 source destination ipv6 netmask'],
|
||||
},
|
||||
'sport_range_1' => {
|
||||
:params => {
|
||||
:name => "100 sport range",
|
||||
:sport => ["1-1024"],
|
||||
:table => "filter",
|
||||
},
|
||||
:args => ["-t", :filter, "-p", :tcp, "-m", "multiport", "--sports", "1:1024", "-m", "comment", "--comment", "100 sport range"],
|
||||
},
|
||||
'sport_range_2' => {
|
||||
:params => {
|
||||
:name => "100 sport range",
|
||||
:sport => ["15","512-1024"],
|
||||
:table => "filter",
|
||||
},
|
||||
:args => ["-t", :filter, "-p", :tcp, "-m", "multiport", "--sports", "15,512:1024", "-m", "comment", "--comment", "100 sport range"],
|
||||
},
|
||||
'dport_range_1' => {
|
||||
:params => {
|
||||
:name => "100 sport range",
|
||||
:dport => ["1-1024"],
|
||||
:table => "filter",
|
||||
},
|
||||
:args => ["-t", :filter, "-p", :tcp, "-m", "multiport", "--dports", "1:1024", "-m", "comment", "--comment", "100 sport range"],
|
||||
},
|
||||
'dport_range_2' => {
|
||||
:params => {
|
||||
:name => "100 sport range",
|
||||
:dport => ["15","512-1024"],
|
||||
:table => "filter",
|
||||
},
|
||||
:args => ["-t", :filter, "-p", :tcp, "-m", "multiport", "--dports", "15,512:1024", "-m", "comment", "--comment", "100 sport range"],
|
||||
},
|
||||
'dst_type_1' => {
|
||||
:params => {
|
||||
:name => '000 dst_type',
|
||||
:table => 'filter',
|
||||
:dst_type => 'LOCAL',
|
||||
},
|
||||
:args => ['-t', :filter, '-p', :tcp, '-m', 'addrtype', '--dst-type', :LOCAL, '-m', 'comment', '--comment', '000 dst_type'],
|
||||
},
|
||||
'src_type_1' => {
|
||||
:params => {
|
||||
:name => '000 src_type',
|
||||
:table => 'filter',
|
||||
:src_type => 'LOCAL',
|
||||
},
|
||||
:args => ['-t', :filter, '-p', :tcp, '-m', 'addrtype', '--src-type', :LOCAL, '-m', 'comment', '--comment', '000 src_type'],
|
||||
},
|
||||
'dst_range_1' => {
|
||||
:params => {
|
||||
:name => '000 dst_range',
|
||||
:table => 'filter',
|
||||
:dst_range => '10.0.0.1-10.0.0.10',
|
||||
},
|
||||
:args => ['-t', :filter, '-p', :tcp, '-m', 'iprange', '--dst-range', '10.0.0.1-10.0.0.10', '-m', 'comment', '--comment', '000 dst_range'],
|
||||
},
|
||||
'src_range_1' => {
|
||||
:params => {
|
||||
:name => '000 src_range',
|
||||
:table => 'filter',
|
||||
:dst_range => '10.0.0.1-10.0.0.10',
|
||||
},
|
||||
:args => ['-t', :filter, '-p', :tcp, '-m', 'iprange', '--dst-range', '10.0.0.1-10.0.0.10', '-m', 'comment', '--comment', '000 src_range'],
|
||||
},
|
||||
'tcp_flags_1' => {
|
||||
:params => {
|
||||
:name => "000 initiation",
|
||||
:tcp_flags => "SYN,RST,ACK,FIN SYN",
|
||||
:table => "filter",
|
||||
},
|
||||
|
||||
:args => ["-t", :filter, "-p", :tcp, "-m", "tcp", "--tcp-flags", "SYN,RST,ACK,FIN", "SYN", "-m", "comment", "--comment", "000 initiation",]
|
||||
},
|
||||
'states_set_from_array' => {
|
||||
:params => {
|
||||
:name => "100 states_set_from_array",
|
||||
:table => "filter",
|
||||
:state => ['ESTABLISHED', 'INVALID']
|
||||
},
|
||||
:args => ["-t", :filter, "-p", :tcp, "-m", "comment", "--comment", "100 states_set_from_array",
|
||||
"-m", "state", "--state", "ESTABLISHED,INVALID"],
|
||||
},
|
||||
'ctstates_set_from_array' => {
|
||||
:params => {
|
||||
:name => "100 ctstates_set_from_array",
|
||||
:table => "filter",
|
||||
:ctstate => ['ESTABLISHED', 'INVALID']
|
||||
},
|
||||
:args => ["-t", :filter, "-p", :tcp, "-m", "comment", "--comment", "100 ctstates_set_from_array",
|
||||
"-m", "conntrack", "--ctstate", "ESTABLISHED,INVALID"],
|
||||
},
|
||||
'comment_string_character_validation' => {
|
||||
:params => {
|
||||
:name => "000 allow from 192.168.0.1, please",
|
||||
:table => 'filter',
|
||||
:source => '192.168.0.1'
|
||||
},
|
||||
:args => ['-t', :filter, '-s', '192.168.0.1/32', '-p', :tcp, '-m', 'comment', '--comment', '000 allow from 192.168.0.1, please'],
|
||||
},
|
||||
'port_property' => {
|
||||
:params => {
|
||||
:name => '001 port property',
|
||||
:table => 'filter',
|
||||
:port => '80',
|
||||
},
|
||||
:args => ['-t', :filter, '-p', :tcp, '-m', 'multiport', '--ports', '80', '-m', 'comment', '--comment', '001 port property'],
|
||||
},
|
||||
'log_level_debug' => {
|
||||
:params => {
|
||||
:name => '956 INPUT log-level',
|
||||
:table => 'filter',
|
||||
:state => 'NEW',
|
||||
:jump => 'LOG',
|
||||
:log_level => 'debug'
|
||||
},
|
||||
:args => ['-t', :filter, '-p', :tcp, '-m', 'comment', '--comment', '956 INPUT log-level', '-m', 'state', '--state', 'NEW', '-j', 'LOG', '--log-level', '7'],
|
||||
},
|
||||
'log_level_warn' => {
|
||||
:params => {
|
||||
:name => '956 INPUT log-level',
|
||||
:table => 'filter',
|
||||
:state => 'NEW',
|
||||
:jump => 'LOG',
|
||||
:log_level => 'warn'
|
||||
},
|
||||
:args => ['-t', :filter, '-p', :tcp, '-m', 'comment', '--comment', '956 INPUT log-level', '-m', 'state', '--state', 'NEW', '-j', 'LOG', '--log-level', '4'],
|
||||
},
|
||||
'load_limit_module_and_implicit_burst' => {
|
||||
:params => {
|
||||
:name => '057 INPUT limit NTP',
|
||||
:table => 'filter',
|
||||
:dport => '123',
|
||||
:limit => '15/hour'
|
||||
},
|
||||
:args => ['-t', :filter, '-p', :tcp, '-m', 'multiport', '--dports', '123', '-m', 'comment', '--comment', '057 INPUT limit NTP', '-m', 'limit', '--limit', '15/hour'],
|
||||
},
|
||||
'limit_with_explicit_burst' => {
|
||||
:params => {
|
||||
:name => '057 INPUT limit NTP',
|
||||
:table => 'filter',
|
||||
:dport => '123',
|
||||
:limit => '30/hour',
|
||||
:burst => '10'
|
||||
},
|
||||
:args => ['-t', :filter, '-p', :tcp, '-m', 'multiport', '--dports', '123', '-m', 'comment', '--comment', '057 INPUT limit NTP', '-m', 'limit', '--limit', '30/hour', '--limit-burst', '10'],
|
||||
},
|
||||
'proto_ipencap' => {
|
||||
:params => {
|
||||
:name => '0100 INPUT accept ipencap',
|
||||
:table => 'filter',
|
||||
:proto => 'ipencap',
|
||||
},
|
||||
:args => ['-t', :filter, '-p', :ipencap, '-m', 'comment', '--comment', '0100 INPUT accept ipencap'],
|
||||
},
|
||||
'load_uid_owner_filter_module' => {
|
||||
:params => {
|
||||
:name => '057 OUTPUT uid root only',
|
||||
:table => 'filter',
|
||||
:uid => 'root',
|
||||
:action => 'accept',
|
||||
:chain => 'OUTPUT',
|
||||
:proto => 'all',
|
||||
},
|
||||
:args => ['-t', :filter, '-p', :all, '-m', 'owner', '--uid-owner', 'root', '-m', 'comment', '--comment', '057 OUTPUT uid root only', '-j', 'ACCEPT'],
|
||||
},
|
||||
'load_uid_owner_postrouting_module' => {
|
||||
:params => {
|
||||
:name => '057 POSTROUTING uid root only',
|
||||
:table => 'mangle',
|
||||
:uid => 'root',
|
||||
:action => 'accept',
|
||||
:chain => 'POSTROUTING',
|
||||
:proto => 'all',
|
||||
},
|
||||
:args => ['-t', :mangle, '-p', :all, '-m', 'owner', '--uid-owner', 'root', '-m', 'comment', '--comment', '057 POSTROUTING uid root only', '-j', 'ACCEPT'],
|
||||
},
|
||||
'load_gid_owner_filter_module' => {
|
||||
:params => {
|
||||
:name => '057 OUTPUT gid root only',
|
||||
:table => 'filter',
|
||||
:chain => 'OUTPUT',
|
||||
:gid => 'root',
|
||||
:action => 'accept',
|
||||
:proto => 'all',
|
||||
},
|
||||
:args => ['-t', :filter, '-p', :all, '-m', 'owner', '--gid-owner', 'root', '-m', 'comment', '--comment', '057 OUTPUT gid root only', '-j', 'ACCEPT'],
|
||||
},
|
||||
'load_gid_owner_postrouting_module' => {
|
||||
:params => {
|
||||
:name => '057 POSTROUTING gid root only',
|
||||
:table => 'mangle',
|
||||
:gid => 'root',
|
||||
:action => 'accept',
|
||||
:chain => 'POSTROUTING',
|
||||
:proto => 'all',
|
||||
},
|
||||
:args => ['-t', :mangle, '-p', :all, '-m', 'owner', '--gid-owner', 'root', '-m', 'comment', '--comment', '057 POSTROUTING gid root only', '-j', 'ACCEPT'],
|
||||
},
|
||||
'mark_set-mark_int' => {
|
||||
:params => {
|
||||
:name => '058 set-mark 1000',
|
||||
:table => 'mangle',
|
||||
:jump => 'MARK',
|
||||
:chain => 'PREROUTING',
|
||||
:set_mark => '1000',
|
||||
},
|
||||
:args => ['-t', :mangle, '-p', :tcp, '-m', 'comment', '--comment', '058 set-mark 1000', '-j', 'MARK', '--set-xmark', '0x3e8/0xffffffff'],
|
||||
},
|
||||
'mark_set-mark_hex' => {
|
||||
:params => {
|
||||
:name => '058 set-mark 0x32',
|
||||
:table => 'mangle',
|
||||
:jump => 'MARK',
|
||||
:chain => 'PREROUTING',
|
||||
:set_mark => '0x32',
|
||||
},
|
||||
:args => ['-t', :mangle, '-p', :tcp, '-m', 'comment', '--comment', '058 set-mark 0x32', '-j', 'MARK', '--set-xmark', '0x32/0xffffffff'],
|
||||
},
|
||||
'mark_set-mark_hex_with_hex_mask' => {
|
||||
:params => {
|
||||
:name => '058 set-mark 0x32/0xffffffff',
|
||||
:table => 'mangle',
|
||||
:jump => 'MARK',
|
||||
:chain => 'PREROUTING',
|
||||
:set_mark => '0x32/0xffffffff',
|
||||
},
|
||||
:args => ['-t', :mangle, '-p', :tcp, '-m', 'comment', '--comment', '058 set-mark 0x32/0xffffffff', '-j', 'MARK', '--set-xmark', '0x32/0xffffffff'],
|
||||
},
|
||||
'mark_set-mark_hex_with_mask' => {
|
||||
:params => {
|
||||
:name => '058 set-mark 0x32/4',
|
||||
:table => 'mangle',
|
||||
:jump => 'MARK',
|
||||
:chain => 'PREROUTING',
|
||||
:set_mark => '0x32/4',
|
||||
},
|
||||
:args => ['-t', :mangle, '-p', :tcp, '-m', 'comment', '--comment', '058 set-mark 0x32/4', '-j', 'MARK', '--set-xmark', '0x32/0x4'],
|
||||
},
|
||||
'iniface_1' => {
|
||||
:params => {
|
||||
:name => '060 iniface',
|
||||
:table => 'filter',
|
||||
:action => 'drop',
|
||||
:chain => 'INPUT',
|
||||
:iniface => 'eth0',
|
||||
},
|
||||
:args => ["-t", :filter, "-i", "eth0", "-p", :tcp, "-m", "comment", "--comment", "060 iniface", "-j", "DROP"],
|
||||
},
|
||||
'iniface_with_vlans_1' => {
|
||||
:params => {
|
||||
:name => '060 iniface',
|
||||
:table => 'filter',
|
||||
:action => 'drop',
|
||||
:chain => 'INPUT',
|
||||
:iniface => 'eth0.234',
|
||||
},
|
||||
:args => ["-t", :filter, "-i", "eth0.234", "-p", :tcp, "-m", "comment", "--comment", "060 iniface", "-j", "DROP"],
|
||||
},
|
||||
'iniface_with_plus_1' => {
|
||||
:params => {
|
||||
:name => '060 iniface',
|
||||
:table => 'filter',
|
||||
:action => 'drop',
|
||||
:chain => 'INPUT',
|
||||
:iniface => 'eth+',
|
||||
},
|
||||
:args => ["-t", :filter, "-i", "eth+", "-p", :tcp, "-m", "comment", "--comment", "060 iniface", "-j", "DROP"],
|
||||
},
|
||||
'outiface_1' => {
|
||||
:params => {
|
||||
:name => '060 outiface',
|
||||
:table => 'filter',
|
||||
:action => 'drop',
|
||||
:chain => 'OUTPUT',
|
||||
:outiface => 'eth0',
|
||||
},
|
||||
:args => ["-t", :filter, "-o", "eth0", "-p", :tcp, "-m", "comment", "--comment", "060 outiface", "-j", "DROP"],
|
||||
},
|
||||
'outiface_with_vlans_1' => {
|
||||
:params => {
|
||||
:name => '060 outiface',
|
||||
:table => 'filter',
|
||||
:action => 'drop',
|
||||
:chain => 'OUTPUT',
|
||||
:outiface => 'eth0.234',
|
||||
},
|
||||
:args => ["-t", :filter, "-o", "eth0.234", "-p", :tcp, "-m", "comment", "--comment", "060 outiface", "-j", "DROP"],
|
||||
},
|
||||
'outiface_with_plus_1' => {
|
||||
:params => {
|
||||
:name => '060 outiface',
|
||||
:table => 'filter',
|
||||
:action => 'drop',
|
||||
:chain => 'OUTPUT',
|
||||
:outiface => 'eth+',
|
||||
},
|
||||
:args => ["-t", :filter, "-o", "eth+", "-p", :tcp, "-m", "comment", "--comment", "060 outiface", "-j", "DROP"],
|
||||
},
|
||||
'pkttype multicast' => {
|
||||
:params => {
|
||||
:name => '062 pkttype multicast',
|
||||
:table => "filter",
|
||||
:action => 'accept',
|
||||
:chain => 'INPUT',
|
||||
:iniface => 'eth0',
|
||||
:pkttype => 'multicast',
|
||||
},
|
||||
:args => ["-t", :filter, "-i", "eth0", "-p", :tcp, "-m", "pkttype", "--pkt-type", :multicast, "-m", "comment", "--comment", "062 pkttype multicast", "-j", "ACCEPT"],
|
||||
},
|
||||
'socket_option' => {
|
||||
:params => {
|
||||
:name => '050 socket option',
|
||||
:table => 'mangle',
|
||||
:action => 'accept',
|
||||
:chain => 'PREROUTING',
|
||||
:socket => true,
|
||||
},
|
||||
:args => ['-t', :mangle, '-p', :tcp, '-m', 'socket', '-m', 'comment', '--comment', '050 socket option', '-j', 'ACCEPT'],
|
||||
},
|
||||
'isfragment_option' => {
|
||||
:params => {
|
||||
:name => '050 isfragment option',
|
||||
:table => 'filter',
|
||||
:proto => :all,
|
||||
:action => 'accept',
|
||||
:isfragment => true,
|
||||
},
|
||||
:args => ['-t', :filter, '-p', :all, '-f', '-m', 'comment', '--comment', '050 isfragment option', '-j', 'ACCEPT'],
|
||||
},
|
||||
'isfragment_option not changing -f in comment' => {
|
||||
:params => {
|
||||
:name => '050 testcomment-with-fdashf',
|
||||
:table => 'filter',
|
||||
:proto => :all,
|
||||
:action => 'accept',
|
||||
},
|
||||
:args => ['-t', :filter, '-p', :all, '-m', 'comment', '--comment', '050 testcomment-with-fdashf', '-j', 'ACCEPT'],
|
||||
},
|
||||
'connlimit_above' => {
|
||||
:params => {
|
||||
:name => '061 REJECT connlimit_above 10',
|
||||
:table => 'filter',
|
||||
:proto => 'tcp',
|
||||
:dport => ["22"],
|
||||
:connlimit_above => '10',
|
||||
:action => 'reject',
|
||||
},
|
||||
:args => ["-t", :filter, "-p", :tcp, "-m", "multiport", "--dports", "22", "-m", "comment", "--comment", "061 REJECT connlimit_above 10", "-j", "REJECT", "-m", "connlimit", "--connlimit-above", "10"],
|
||||
},
|
||||
'connlimit_above_with_connlimit_mask' => {
|
||||
:params => {
|
||||
:name => '061 REJECT connlimit_above 10 with mask 24',
|
||||
:table => 'filter',
|
||||
:proto => 'tcp',
|
||||
:dport => ["22"],
|
||||
:connlimit_above => '10',
|
||||
:connlimit_mask => '24',
|
||||
:action => 'reject',
|
||||
},
|
||||
:args => ["-t", :filter, "-p", :tcp, "-m", "multiport", "--dports", "22", "-m", "comment", "--comment", "061 REJECT connlimit_above 10 with mask 24", "-j", "REJECT", "-m", "connlimit", "--connlimit-above", "10", "--connlimit-mask", "24"],
|
||||
},
|
||||
'connmark' => {
|
||||
:params => {
|
||||
:name => '062 REJECT connmark',
|
||||
:table => 'filter',
|
||||
:proto => 'all',
|
||||
:connmark => '0x1',
|
||||
:action => 'reject',
|
||||
},
|
||||
:args => ["-t", :filter, "-p", :all, "-m", "comment", "--comment", "062 REJECT connmark", "-j", "REJECT", "-m", "connmark", "--mark", "0x1"],
|
||||
},
|
||||
}
|
29
modules/firewall/spec/spec_helper.rb
Normal file
29
modules/firewall/spec/spec_helper.rb
Normal file
|
@ -0,0 +1,29 @@
|
|||
dir = File.expand_path(File.dirname(__FILE__))
|
||||
$LOAD_PATH.unshift File.join(dir, 'lib')
|
||||
|
||||
# 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')
|
||||
end
|
44
modules/firewall/spec/spec_helper_acceptance.rb
Normal file
44
modules/firewall/spec/spec_helper_acceptance.rb
Normal file
|
@ -0,0 +1,44 @@
|
|||
require 'beaker-rspec'
|
||||
|
||||
def iptables_flush_all_tables
|
||||
['filter', 'nat', 'mangle', 'raw'].each do |t|
|
||||
expect(shell("iptables -t #{t} -F").stderr).to eq("")
|
||||
end
|
||||
end
|
||||
|
||||
def ip6tables_flush_all_tables
|
||||
['filter'].each do |t|
|
||||
expect(shell("ip6tables -t #{t} -F").stderr).to eq("")
|
||||
end
|
||||
end
|
||||
|
||||
unless ENV['RS_PROVISION'] == 'no' or ENV['BEAKER_provision'] == 'no'
|
||||
if hosts.first.is_pe?
|
||||
install_pe
|
||||
else
|
||||
install_puppet
|
||||
end
|
||||
hosts.each do |host|
|
||||
on host, "mkdir -p #{host['distmoduledir']}"
|
||||
end
|
||||
end
|
||||
|
||||
UNSUPPORTED_PLATFORMS = ['windows','Solaris','Darwin']
|
||||
|
||||
RSpec.configure do |c|
|
||||
# Project root
|
||||
proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
||||
|
||||
# Readable test descriptions
|
||||
c.formatter = :documentation
|
||||
|
||||
# Configure all nodes in nodeset
|
||||
c.before :suite do
|
||||
# Install module and dependencies
|
||||
puppet_module_install(:source => proj_root, :module_name => 'firewall')
|
||||
hosts.each do |host|
|
||||
shell('/bin/touch /etc/puppet/hiera.yaml')
|
||||
shell('puppet module install puppetlabs-stdlib --version 3.2.0', { :acceptable_exit_codes => [0,1] })
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,32 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'firewall::linux::archlinux', :type => :class do
|
||||
it { should contain_service('iptables').with(
|
||||
:ensure => 'running',
|
||||
:enable => 'true'
|
||||
)}
|
||||
it { should contain_service('ip6tables').with(
|
||||
:ensure => 'running',
|
||||
:enable => 'true'
|
||||
)}
|
||||
|
||||
context 'ensure => stopped' do
|
||||
let(:params) {{ :ensure => 'stopped' }}
|
||||
it { should contain_service('iptables').with(
|
||||
:ensure => 'stopped'
|
||||
)}
|
||||
it { should contain_service('ip6tables').with(
|
||||
:ensure => 'stopped'
|
||||
)}
|
||||
end
|
||||
|
||||
context 'enable => false' do
|
||||
let(:params) {{ :enable => 'false' }}
|
||||
it { should contain_service('iptables').with(
|
||||
:enable => 'false'
|
||||
)}
|
||||
it { should contain_service('ip6tables').with(
|
||||
:enable => 'false'
|
||||
)}
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'firewall::linux::debian', :type => :class 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]'
|
||||
)}
|
||||
|
||||
context 'enable => false' do
|
||||
let(:params) {{ :enable => 'false' }}
|
||||
it { should contain_service('iptables-persistent').with(
|
||||
:enable => 'false'
|
||||
)}
|
||||
end
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'firewall::linux::redhat', :type => :class do
|
||||
it { should contain_service('iptables').with(
|
||||
:ensure => 'running',
|
||||
:enable => 'true'
|
||||
)}
|
||||
|
||||
context 'ensure => stopped' do
|
||||
let(:params) {{ :ensure => 'stopped' }}
|
||||
it { should contain_service('iptables').with(
|
||||
:ensure => 'stopped'
|
||||
)}
|
||||
end
|
||||
|
||||
context 'enable => false' do
|
||||
let(:params) {{ :enable => 'false' }}
|
||||
it { should contain_service('iptables').with(
|
||||
:enable => 'false'
|
||||
)}
|
||||
end
|
||||
end
|
30
modules/firewall/spec/unit/classes/firewall_linux_spec.rb
Normal file
30
modules/firewall/spec/unit/classes/firewall_linux_spec.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'firewall::linux', :type => :class 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
|
||||
releases = (os == 'Fedora' ? [14,15,'Rawhide'] : [6,7])
|
||||
releases.each do |osrel|
|
||||
context "operatingsystemrelease => #{osrel}" do
|
||||
let(:facts) { facts_default.merge({ :operatingsystem => os,
|
||||
:operatingsystemrelease => osrel}) }
|
||||
it { should contain_class('firewall::linux::redhat').with_require('Package[iptables]') }
|
||||
end
|
||||
end
|
||||
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
|
25
modules/firewall/spec/unit/classes/firewall_spec.rb
Normal file
25
modules/firewall/spec/unit/classes/firewall_spec.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'firewall', :type => :class do
|
||||
context 'kernel => Linux' do
|
||||
let(:facts) {{ :kernel => 'Linux' }}
|
||||
it { should contain_class('firewall::linux').with_ensure('running') }
|
||||
end
|
||||
|
||||
context 'kernel => Windows' do
|
||||
let(:facts) {{ :kernel => 'Windows' }}
|
||||
it { expect { should contain_class('firewall::linux') }.to raise_error(Puppet::Error) }
|
||||
end
|
||||
|
||||
context 'ensure => stopped' do
|
||||
let(:facts) {{ :kernel => 'Linux' }}
|
||||
let(:params) {{ :ensure => 'stopped' }}
|
||||
it { should contain_class('firewall::linux').with_ensure('stopped') }
|
||||
end
|
||||
|
||||
context 'ensure => test' do
|
||||
let(:facts) {{ :kernel => 'Linux' }}
|
||||
let(:params) {{ :ensure => 'test' }}
|
||||
it { expect { should contain_class('firewall::linux') }.to raise_error(Puppet::Error) }
|
||||
end
|
||||
end
|
|
@ -0,0 +1,35 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe "Facter::Util::Fact iptables_persistent_version" do
|
||||
before { Facter.clear }
|
||||
let(:dpkg_cmd) { "dpkg-query -Wf '${Version}' iptables-persistent 2>/dev/null" }
|
||||
|
||||
{
|
||||
"Debian" => "0.0.20090701",
|
||||
"Ubuntu" => "0.5.3ubuntu2",
|
||||
}.each do |os, ver|
|
||||
describe "#{os} package installed" do
|
||||
before {
|
||||
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return(os)
|
||||
allow(Facter::Util::Resolution).to receive(:exec).with(dpkg_cmd).
|
||||
and_return(ver)
|
||||
}
|
||||
it { Facter.fact(:iptables_persistent_version).value.should == ver }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Ubuntu package not installed' do
|
||||
before {
|
||||
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return('Ubuntu')
|
||||
allow(Facter::Util::Resolution).to receive(:exec).with(dpkg_cmd).
|
||||
and_return(nil)
|
||||
}
|
||||
it { Facter.fact(:iptables_persistent_version).value.should be_nil }
|
||||
end
|
||||
|
||||
describe 'CentOS not supported' do
|
||||
before { allow(Facter.fact(:operatingsystem)).to receive(:value).
|
||||
and_return("CentOS") }
|
||||
it { Facter.fact(:iptables_persistent_version).value.should be_nil }
|
||||
end
|
||||
end
|
23
modules/firewall/spec/unit/facter/iptables_spec.rb
Normal file
23
modules/firewall/spec/unit/facter/iptables_spec.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe "Facter::Util::Fact" do
|
||||
before {
|
||||
Facter.clear
|
||||
allow(Facter.fact(:kernel)).to receive(:value).and_return('Linux')
|
||||
allow(Facter.fact(:kernelrelease)).to receive(:value).and_return('2.6')
|
||||
}
|
||||
|
||||
describe 'iptables_version' do
|
||||
it {
|
||||
allow(Facter::Util::Resolution).to receive(:exec).with('iptables --version').
|
||||
and_return('iptables v1.4.7')
|
||||
Facter.fact(:iptables_version).value.should == '1.4.7'
|
||||
}
|
||||
end
|
||||
|
||||
describe 'ip6tables_version' do
|
||||
before { allow(Facter::Util::Resolution).to receive(:exec).
|
||||
with('ip6tables --version').and_return('ip6tables v1.4.7') }
|
||||
it { Facter.fact(:ip6tables_version).value.should == '1.4.7' }
|
||||
end
|
||||
end
|
227
modules/firewall/spec/unit/puppet/provider/iptables_chain_spec.rb
Executable file
227
modules/firewall/spec/unit/puppet/provider/iptables_chain_spec.rb
Executable file
|
@ -0,0 +1,227 @@
|
|||
#!/usr/bin/env rspec
|
||||
|
||||
require 'spec_helper'
|
||||
if Puppet.version < '3.4.0'
|
||||
require 'puppet/provider/confine/exists'
|
||||
else
|
||||
require 'puppet/confine/exists'
|
||||
end
|
||||
|
||||
describe 'iptables chain provider detection' do
|
||||
if Puppet.version < '3.4.0'
|
||||
let(:exists) {
|
||||
Puppet::Provider::Confine::Exists
|
||||
}
|
||||
else
|
||||
let(:exists) {
|
||||
Puppet::Confine::Exists
|
||||
}
|
||||
end
|
||||
|
||||
before :each do
|
||||
# Reset the default provider
|
||||
Puppet::Type.type(:firewallchain).defaultprovider = nil
|
||||
end
|
||||
|
||||
it "should default to iptables provider if /sbin/(eb|ip|ip6)tables[-save] exists" do
|
||||
# Stub lookup for /sbin/iptables & /sbin/iptables-save
|
||||
allow(exists).to receive(:which).with("ebtables").
|
||||
and_return "/sbin/ebtables"
|
||||
allow(exists).to receive(:which).with("ebtables-save").
|
||||
and_return "/sbin/ebtables-save"
|
||||
|
||||
allow(exists).to receive(:which).with("iptables").
|
||||
and_return "/sbin/iptables"
|
||||
allow(exists).to receive(:which).with("iptables-save").
|
||||
and_return "/sbin/iptables-save"
|
||||
|
||||
allow(exists).to receive(:which).with("ip6tables").
|
||||
and_return "/sbin/ip6tables"
|
||||
allow(exists).to receive(:which).with("ip6tables-save").
|
||||
and_return "/sbin/ip6tables-save"
|
||||
|
||||
# Every other command should return false so we don't pick up any
|
||||
# other providers
|
||||
allow(exists).to receive(:which).with() { |value|
|
||||
value !~ /(eb|ip|ip6)tables(-save)?$/
|
||||
}.and_return false
|
||||
|
||||
# Create a resource instance and make sure the provider is iptables
|
||||
resource = Puppet::Type.type(:firewallchain).new({
|
||||
:name => 'test:filter:IPv4',
|
||||
})
|
||||
expect(resource.provider.class.to_s).to eq("Puppet::Type::Firewallchain::ProviderIptables_chain")
|
||||
end
|
||||
end
|
||||
|
||||
describe 'iptables chain provider' do
|
||||
let(:provider) { Puppet::Type.type(:firewallchain).provider(:iptables_chain) }
|
||||
let(:resource) {
|
||||
Puppet::Type.type(:firewallchain).new({
|
||||
:name => ':test:',
|
||||
})
|
||||
}
|
||||
|
||||
before :each do
|
||||
allow(Puppet::Type::Firewallchain).to receive(:defaultprovider).and_return provider
|
||||
allow(provider).to receive(:command).with(:ebtables_save).and_return "/sbin/ebtables-save"
|
||||
allow(provider).to receive(:command).with(:iptables_save).and_return "/sbin/iptables-save"
|
||||
allow(provider).to receive(:command).with(:ip6tables_save).and_return "/sbin/ip6tables-save"
|
||||
end
|
||||
|
||||
it 'should be able to get a list of existing rules' do
|
||||
# Pretend to return nil from iptables
|
||||
allow(provider).to receive(:execute).with(['/sbin/ip6tables-save']).and_return("")
|
||||
allow(provider).to receive(:execute).with(['/sbin/ebtables-save']).and_return("")
|
||||
allow(provider).to receive(:execute).with(['/sbin/iptables-save']).and_return("")
|
||||
|
||||
provider.instances.each do |chain|
|
||||
expect(chain).to be_instance_of(provider)
|
||||
expect(chain.properties[:provider].to_s).to eq(provider.name.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe 'iptables chain resource parsing' do
|
||||
let(:provider) { Puppet::Type.type(:firewallchain).provider(:iptables_chain) }
|
||||
|
||||
before :each do
|
||||
ebtables = ['BROUTE:BROUTING:ethernet',
|
||||
'BROUTE:broute:ethernet',
|
||||
':INPUT:ethernet',
|
||||
':FORWARD:ethernet',
|
||||
':OUTPUT:ethernet',
|
||||
':filter:ethernet',
|
||||
':filterdrop:ethernet',
|
||||
':filterreturn:ethernet',
|
||||
'NAT:PREROUTING:ethernet',
|
||||
'NAT:OUTPUT:ethernet',
|
||||
'NAT:POSTROUTING:ethernet',
|
||||
]
|
||||
allow(provider).to receive(:execute).with(['/sbin/ebtables-save']).and_return('
|
||||
*broute
|
||||
:BROUTING ACCEPT
|
||||
:broute ACCEPT
|
||||
|
||||
*filter
|
||||
:INPUT ACCEPT
|
||||
:FORWARD ACCEPT
|
||||
:OUTPUT ACCEPT
|
||||
:filter ACCEPT
|
||||
:filterdrop DROP
|
||||
:filterreturn RETURN
|
||||
|
||||
*nat
|
||||
:PREROUTING ACCEPT
|
||||
:OUTPUT ACCEPT
|
||||
:POSTROUTING ACCEPT
|
||||
')
|
||||
|
||||
iptables = [
|
||||
'raw:PREROUTING:IPv4',
|
||||
'raw:OUTPUT:IPv4',
|
||||
'raw:raw:IPv4',
|
||||
'mangle:PREROUTING:IPv4',
|
||||
'mangle:INPUT:IPv4',
|
||||
'mangle:FORWARD:IPv4',
|
||||
'mangle:OUTPUT:IPv4',
|
||||
'mangle:POSTROUTING:IPv4',
|
||||
'mangle:mangle:IPv4',
|
||||
'NAT:PREROUTING:IPv4',
|
||||
'NAT:OUTPUT:IPv4',
|
||||
'NAT:POSTROUTING:IPv4',
|
||||
'NAT:mangle:IPv4',
|
||||
'NAT:mangle:IPv4',
|
||||
'NAT:mangle:IPv4',
|
||||
':$5()*&%\'"^$): :IPv4',
|
||||
]
|
||||
allow(provider).to receive(:execute).with(['/sbin/iptables-save']).and_return('
|
||||
# Generated by iptables-save v1.4.9 on Mon Jan 2 01:20:06 2012
|
||||
*raw
|
||||
:PREROUTING ACCEPT [12:1780]
|
||||
:OUTPUT ACCEPT [19:1159]
|
||||
:raw - [0:0]
|
||||
COMMIT
|
||||
# Completed on Mon Jan 2 01:20:06 2012
|
||||
# Generated by iptables-save v1.4.9 on Mon Jan 2 01:20:06 2012
|
||||
*mangle
|
||||
:PREROUTING ACCEPT [12:1780]
|
||||
:INPUT ACCEPT [12:1780]
|
||||
:FORWARD ACCEPT [0:0]
|
||||
:OUTPUT ACCEPT [19:1159]
|
||||
:POSTROUTING ACCEPT [19:1159]
|
||||
:mangle - [0:0]
|
||||
COMMIT
|
||||
# Completed on Mon Jan 2 01:20:06 2012
|
||||
# Generated by iptables-save v1.4.9 on Mon Jan 2 01:20:06 2012
|
||||
*nat
|
||||
:PREROUTING ACCEPT [2242:639750]
|
||||
:OUTPUT ACCEPT [5176:326206]
|
||||
:POSTROUTING ACCEPT [5162:325382]
|
||||
COMMIT
|
||||
# Completed on Mon Jan 2 01:20:06 2012
|
||||
# Generated by iptables-save v1.4.9 on Mon Jan 2 01:20:06 2012
|
||||
*filter
|
||||
:INPUT ACCEPT [0:0]
|
||||
:FORWARD DROP [0:0]
|
||||
:OUTPUT ACCEPT [5673:420879]
|
||||
:$5()*&%\'"^$): - [0:0]
|
||||
COMMIT
|
||||
# Completed on Mon Jan 2 01:20:06 2012
|
||||
')
|
||||
ip6tables = [
|
||||
'raw:PREROUTING:IPv6',
|
||||
'raw:OUTPUT:IPv6',
|
||||
'raw:ff:IPv6',
|
||||
'mangle:PREROUTING:IPv6',
|
||||
'mangle:INPUT:IPv6',
|
||||
'mangle:FORWARD:IPv6',
|
||||
'mangle:OUTPUT:IPv6',
|
||||
'mangle:POSTROUTING:IPv6',
|
||||
'mangle:ff:IPv6',
|
||||
':INPUT:IPv6',
|
||||
':FORWARD:IPv6',
|
||||
':OUTPUT:IPv6',
|
||||
':test:IPv6',
|
||||
]
|
||||
allow(provider).to receive(:execute).with(['/sbin/ip6tables-save']).and_return('
|
||||
# Generated by ip6tables-save v1.4.9 on Mon Jan 2 01:31:39 2012
|
||||
*raw
|
||||
:PREROUTING ACCEPT [2173:489241]
|
||||
:OUTPUT ACCEPT [0:0]
|
||||
:ff - [0:0]
|
||||
COMMIT
|
||||
# Completed on Mon Jan 2 01:31:39 2012
|
||||
# Generated by ip6tables-save v1.4.9 on Mon Jan 2 01:31:39 2012
|
||||
*mangle
|
||||
:PREROUTING ACCEPT [2301:518373]
|
||||
:INPUT ACCEPT [0:0]
|
||||
:FORWARD ACCEPT [0:0]
|
||||
:OUTPUT ACCEPT [0:0]
|
||||
:POSTROUTING ACCEPT [0:0]
|
||||
:ff - [0:0]
|
||||
COMMIT
|
||||
# Completed on Mon Jan 2 01:31:39 2012
|
||||
# Generated by ip6tables-save v1.4.9 on Mon Jan 2 01:31:39 2012
|
||||
*filter
|
||||
:INPUT ACCEPT [0:0]
|
||||
:FORWARD DROP [0:0]
|
||||
:OUTPUT ACCEPT [20:1292]
|
||||
:test - [0:0]
|
||||
COMMIT
|
||||
# Completed on Mon Jan 2 01:31:39 2012
|
||||
')
|
||||
@all = ebtables + iptables + ip6tables
|
||||
# IPv4 and IPv6 names also exist as resources {table}:{chain}:IP and {table}:{chain}:
|
||||
iptables.each { |name| @all += [ name[0..-3], name[0..-5] ] }
|
||||
ip6tables.each { |name| @all += [ name[0..-3], name[0..-5] ] }
|
||||
end
|
||||
|
||||
it 'should have all in parsed resources' do
|
||||
provider.instances.each do |resource|
|
||||
@all.include?(resource.name)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
410
modules/firewall/spec/unit/puppet/provider/iptables_spec.rb
Normal file
410
modules/firewall/spec/unit/puppet/provider/iptables_spec.rb
Normal file
|
@ -0,0 +1,410 @@
|
|||
#!/usr/bin/env rspec
|
||||
|
||||
require 'spec_helper'
|
||||
if Puppet.version < '3.4.0'
|
||||
require 'puppet/provider/confine/exists'
|
||||
else
|
||||
require 'puppet/confine/exists'
|
||||
end
|
||||
|
||||
describe 'iptables provider detection' do
|
||||
if Puppet.version < '3.4.0'
|
||||
let(:exists) {
|
||||
Puppet::Provider::Confine::Exists
|
||||
}
|
||||
else
|
||||
let(:exists) {
|
||||
Puppet::Confine::Exists
|
||||
}
|
||||
end
|
||||
|
||||
before :each do
|
||||
# Reset the default provider
|
||||
Puppet::Type.type(:firewall).defaultprovider = nil
|
||||
end
|
||||
|
||||
it "should default to iptables provider if /sbin/iptables[-save] exists" do
|
||||
# Stub lookup for /sbin/iptables & /sbin/iptables-save
|
||||
allow(exists).to receive(:which).with("iptables").
|
||||
and_return "/sbin/iptables"
|
||||
allow(exists).to receive(:which).with("iptables-save").
|
||||
and_return "/sbin/iptables-save"
|
||||
|
||||
# Every other command should return false so we don't pick up any
|
||||
# other providers
|
||||
allow(exists).to receive(:which).with() { |value|
|
||||
! ["iptables","iptables-save"].include?(value)
|
||||
}.and_return false
|
||||
|
||||
# Create a resource instance and make sure the provider is iptables
|
||||
resource = Puppet::Type.type(:firewall).new({
|
||||
:name => '000 test foo',
|
||||
})
|
||||
expect(resource.provider.class.to_s).to eq("Puppet::Type::Firewall::ProviderIptables")
|
||||
end
|
||||
end
|
||||
|
||||
describe 'iptables provider' do
|
||||
let(:provider) { Puppet::Type.type(:firewall).provider(:iptables) }
|
||||
let(:resource) {
|
||||
Puppet::Type.type(:firewall).new({
|
||||
:name => '000 test foo',
|
||||
:action => 'accept',
|
||||
})
|
||||
}
|
||||
|
||||
before :each do
|
||||
allow(Puppet::Type::Firewall).to receive(:defaultprovider).and_return provider
|
||||
allow(provider).to receive(:command).with(:iptables_save).and_return "/sbin/iptables-save"
|
||||
|
||||
# Stub iptables version
|
||||
allow(Facter.fact(:iptables_version)).to receive(:value).and_return("1.4.2")
|
||||
|
||||
allow(Puppet::Util::Execution).to receive(:execute).and_return ""
|
||||
allow(Puppet::Util).to receive(:which).with("iptables-save").
|
||||
and_return "/sbin/iptables-save"
|
||||
end
|
||||
|
||||
it 'should be able to get a list of existing rules' do
|
||||
provider.instances.each do |rule|
|
||||
expect(rule).to be_instance_of(provider)
|
||||
expect(rule.properties[:provider].to_s).to eq(provider.name.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
it 'should ignore lines with fatal errors' do
|
||||
allow(Puppet::Util::Execution).to receive(:execute).with(['/sbin/iptables-save']).
|
||||
and_return("FATAL: Could not load /lib/modules/2.6.18-028stab095.1/modules.dep: No such file or directory")
|
||||
|
||||
expect(provider.instances.length).to be_zero
|
||||
end
|
||||
|
||||
describe '#insert_order' do
|
||||
let(:iptables_save_output) { [
|
||||
'-A INPUT -s 8.0.0.2/32 -p tcp -m multiport --ports 100 -m comment --comment "100 test" -j ACCEPT',
|
||||
'-A INPUT -s 8.0.0.3/32 -p tcp -m multiport --ports 200 -m comment --comment "200 test" -j ACCEPT',
|
||||
'-A INPUT -s 8.0.0.4/32 -p tcp -m multiport --ports 300 -m comment --comment "300 test" -j ACCEPT'
|
||||
] }
|
||||
let(:resources) do
|
||||
iptables_save_output.each_with_index.collect { |l,index| provider.rule_to_hash(l, 'filter', index) }
|
||||
end
|
||||
let(:providers) do
|
||||
resources.collect { |r| provider.new(r) }
|
||||
end
|
||||
it 'understands offsets for adding rules to the beginning' do
|
||||
resource = Puppet::Type.type(:firewall).new({ :name => '001 test', })
|
||||
allow(resource.provider.class).to receive(:instances).and_return(providers)
|
||||
expect(resource.provider.insert_order).to eq(1) # 1-indexed
|
||||
end
|
||||
it 'understands offsets for editing rules at the beginning' do
|
||||
resource = Puppet::Type.type(:firewall).new({ :name => '100 test', })
|
||||
allow(resource.provider.class).to receive(:instances).and_return(providers)
|
||||
expect(resource.provider.insert_order).to eq(1)
|
||||
end
|
||||
it 'understands offsets for adding rules to the middle' do
|
||||
resource = Puppet::Type.type(:firewall).new({ :name => '101 test', })
|
||||
allow(resource.provider.class).to receive(:instances).and_return(providers)
|
||||
expect(resource.provider.insert_order).to eq(2)
|
||||
end
|
||||
it 'understands offsets for editing rules at the middle' do
|
||||
resource = Puppet::Type.type(:firewall).new({ :name => '200 test', })
|
||||
allow(resource.provider.class).to receive(:instances).and_return(providers)
|
||||
expect(resource.provider.insert_order).to eq(2)
|
||||
end
|
||||
it 'understands offsets for adding rules to the end' do
|
||||
resource = Puppet::Type.type(:firewall).new({ :name => '301 test', })
|
||||
allow(resource.provider.class).to receive(:instances).and_return(providers)
|
||||
expect(resource.provider.insert_order).to eq(4)
|
||||
end
|
||||
it 'understands offsets for editing rules at the end' do
|
||||
resource = Puppet::Type.type(:firewall).new({ :name => '300 test', })
|
||||
allow(resource.provider.class).to receive(:instances).and_return(providers)
|
||||
expect(resource.provider.insert_order).to eq(3)
|
||||
end
|
||||
|
||||
context 'with unname rules between' do
|
||||
let(:iptables_save_output) { [
|
||||
'-A INPUT -s 8.0.0.2/32 -p tcp -m multiport --ports 100 -m comment --comment "100 test" -j ACCEPT',
|
||||
'-A INPUT -s 8.0.0.2/32 -p tcp -m multiport --ports 150 -m comment --comment "150 test" -j ACCEPT',
|
||||
'-A INPUT -s 8.0.0.3/32 -p tcp -m multiport --ports 200 -j ACCEPT',
|
||||
'-A INPUT -s 8.0.0.3/32 -p tcp -m multiport --ports 250 -j ACCEPT',
|
||||
'-A INPUT -s 8.0.0.4/32 -p tcp -m multiport --ports 300 -m comment --comment "300 test" -j ACCEPT',
|
||||
'-A INPUT -s 8.0.0.4/32 -p tcp -m multiport --ports 350 -m comment --comment "350 test" -j ACCEPT',
|
||||
] }
|
||||
it 'understands offsets for adding rules before unnamed rules' do
|
||||
resource = Puppet::Type.type(:firewall).new({ :name => '001 test', })
|
||||
allow(resource.provider.class).to receive(:instances).and_return(providers)
|
||||
expect(resource.provider.insert_order).to eq(1)
|
||||
end
|
||||
it 'understands offsets for editing rules before unnamed rules' do
|
||||
resource = Puppet::Type.type(:firewall).new({ :name => '100 test', })
|
||||
allow(resource.provider.class).to receive(:instances).and_return(providers)
|
||||
expect(resource.provider.insert_order).to eq(1)
|
||||
end
|
||||
it 'understands offsets for adding rules between managed rules' do
|
||||
resource = Puppet::Type.type(:firewall).new({ :name => '120 test', })
|
||||
allow(resource.provider.class).to receive(:instances).and_return(providers)
|
||||
expect(resource.provider.insert_order).to eq(2)
|
||||
end
|
||||
it 'understands offsets for adding rules between unnamed rules' do
|
||||
resource = Puppet::Type.type(:firewall).new({ :name => '151 test', })
|
||||
allow(resource.provider.class).to receive(:instances).and_return(providers)
|
||||
expect(resource.provider.insert_order).to eq(3)
|
||||
end
|
||||
it 'understands offsets for adding rules after unnamed rules' do
|
||||
resource = Puppet::Type.type(:firewall).new({ :name => '351 test', })
|
||||
allow(resource.provider.class).to receive(:instances).and_return(providers)
|
||||
expect(resource.provider.insert_order).to eq(7)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with unname rules before and after' do
|
||||
let(:iptables_save_output) { [
|
||||
'-A INPUT -s 8.0.0.3/32 -p tcp -m multiport --ports 050 -j ACCEPT',
|
||||
'-A INPUT -s 8.0.0.3/32 -p tcp -m multiport --ports 090 -j ACCEPT',
|
||||
'-A INPUT -s 8.0.0.2/32 -p tcp -m multiport --ports 100 -m comment --comment "100 test" -j ACCEPT',
|
||||
'-A INPUT -s 8.0.0.2/32 -p tcp -m multiport --ports 150 -m comment --comment "150 test" -j ACCEPT',
|
||||
'-A INPUT -s 8.0.0.3/32 -p tcp -m multiport --ports 200 -j ACCEPT',
|
||||
'-A INPUT -s 8.0.0.3/32 -p tcp -m multiport --ports 250 -j ACCEPT',
|
||||
'-A INPUT -s 8.0.0.4/32 -p tcp -m multiport --ports 300 -m comment --comment "300 test" -j ACCEPT',
|
||||
'-A INPUT -s 8.0.0.4/32 -p tcp -m multiport --ports 350 -m comment --comment "350 test" -j ACCEPT',
|
||||
'-A INPUT -s 8.0.0.5/32 -p tcp -m multiport --ports 400 -j ACCEPT',
|
||||
'-A INPUT -s 8.0.0.5/32 -p tcp -m multiport --ports 450 -j ACCEPT',
|
||||
] }
|
||||
it 'understands offsets for adding rules before unnamed rules' do
|
||||
resource = Puppet::Type.type(:firewall).new({ :name => '001 test', })
|
||||
allow(resource.provider.class).to receive(:instances).and_return(providers)
|
||||
expect(resource.provider.insert_order).to eq(1)
|
||||
end
|
||||
it 'understands offsets for editing rules before unnamed rules' do
|
||||
resource = Puppet::Type.type(:firewall).new({ :name => '100 test', })
|
||||
allow(resource.provider.class).to receive(:instances).and_return(providers)
|
||||
expect(resource.provider.insert_order).to eq(3)
|
||||
end
|
||||
it 'understands offsets for adding rules between managed rules' do
|
||||
resource = Puppet::Type.type(:firewall).new({ :name => '120 test', })
|
||||
allow(resource.provider.class).to receive(:instances).and_return(providers)
|
||||
expect(resource.provider.insert_order).to eq(4)
|
||||
end
|
||||
it 'understands offsets for adding rules between unnamed rules' do
|
||||
resource = Puppet::Type.type(:firewall).new({ :name => '151 test', })
|
||||
allow(resource.provider.class).to receive(:instances).and_return(providers)
|
||||
expect(resource.provider.insert_order).to eq(5)
|
||||
end
|
||||
it 'understands offsets for adding rules after unnamed rules' do
|
||||
resource = Puppet::Type.type(:firewall).new({ :name => '351 test', })
|
||||
allow(resource.provider.class).to receive(:instances).and_return(providers)
|
||||
expect(resource.provider.insert_order).to eq(9)
|
||||
end
|
||||
it 'understands offsets for adding rules at the end' do
|
||||
resource = Puppet::Type.type(:firewall).new({ :name => '950 test', })
|
||||
allow(resource.provider.class).to receive(:instances).and_return(providers)
|
||||
expect(resource.provider.insert_order).to eq(11)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Load in ruby hash for test fixtures.
|
||||
load 'spec/fixtures/iptables/conversion_hash.rb'
|
||||
|
||||
describe 'when converting rules to resources' do
|
||||
ARGS_TO_HASH.each do |test_name,data|
|
||||
describe "for test data '#{test_name}'" do
|
||||
let(:resource) { provider.rule_to_hash(data[:line], data[:table], 0) }
|
||||
|
||||
# If this option is enabled, make sure the parameters exactly match
|
||||
if data[:compare_all] then
|
||||
it "the parameter hash keys should be the same as returned by rules_to_hash" do
|
||||
expect(resource.keys).to match_array(data[:params].keys)
|
||||
end
|
||||
end
|
||||
|
||||
# Iterate across each parameter, creating an example for comparison
|
||||
data[:params].each do |param_name, param_value|
|
||||
it "the parameter '#{param_name.to_s}' should match #{param_value.inspect}" do
|
||||
# booleans get cludged to string "true"
|
||||
if param_value == true then
|
||||
expect(resource[param_name]).to be_true
|
||||
else
|
||||
expect(resource[param_name]).to eq(data[:params][param_name])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when working out general_args' do
|
||||
HASH_TO_ARGS.each do |test_name,data|
|
||||
describe "for test data '#{test_name}'" do
|
||||
let(:resource) { Puppet::Type.type(:firewall).new(data[:params]) }
|
||||
let(:provider) { Puppet::Type.type(:firewall).provider(:iptables) }
|
||||
let(:instance) { provider.new(resource) }
|
||||
|
||||
it 'general_args should be valid' do
|
||||
expect(instance.general_args.flatten).to eq(data[:args])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when converting rules without comments to resources' do
|
||||
let(:sample_rule) {
|
||||
'-A INPUT -s 1.1.1.1 -d 1.1.1.1 -p tcp -m multiport --dports 7061,7062 -m multiport --sports 7061,7062 -j ACCEPT'
|
||||
}
|
||||
let(:resource) { provider.rule_to_hash(sample_rule, 'filter', 0) }
|
||||
let(:instance) { provider.new(resource) }
|
||||
|
||||
it 'rule name contains a MD5 sum of the line' do
|
||||
expect(resource[:name]).to eq("9000 #{Digest::MD5.hexdigest(resource[:line])}")
|
||||
end
|
||||
|
||||
it 'parsed the rule arguments correctly' do
|
||||
expect(resource[:chain]).to eq('INPUT')
|
||||
expect(resource[:source]).to eq('1.1.1.1/32')
|
||||
expect(resource[:destination]).to eq('1.1.1.1/32')
|
||||
expect(resource[:proto]).to eq('tcp')
|
||||
expect(resource[:dport]).to eq(['7061', '7062'])
|
||||
expect(resource[:sport]).to eq(['7061', '7062'])
|
||||
expect(resource[:action]).to eq('accept')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when converting existing rules generates by system-config-firewall-tui to resources' do
|
||||
let(:sample_rule) {
|
||||
# as generated by iptables-save from rules created with system-config-firewall-tui
|
||||
'-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT'
|
||||
}
|
||||
let(:resource) { provider.rule_to_hash(sample_rule, 'filter', 0) }
|
||||
let(:instance) { provider.new(resource) }
|
||||
|
||||
it 'rule name contains a MD5 sum of the line' do
|
||||
expect(resource[:name]).to eq("9000 #{Digest::MD5.hexdigest(resource[:line])}")
|
||||
end
|
||||
|
||||
it 'parse arguments' do
|
||||
expect(resource[:chain]).to eq('INPUT')
|
||||
expect(resource[:proto]).to eq('tcp')
|
||||
expect(resource[:dport]).to eq(['22'])
|
||||
expect(resource[:state]).to eq(['NEW'])
|
||||
expect(resource[:action]).to eq('accept')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when creating resources' do
|
||||
let(:instance) { provider.new(resource) }
|
||||
|
||||
it 'insert_args should be an array' do
|
||||
expect(instance.insert_args.class).to eq(Array)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when modifying resources' do
|
||||
let(:instance) { provider.new(resource) }
|
||||
|
||||
it 'update_args should be an array' do
|
||||
expect(instance.update_args.class).to eq(Array)
|
||||
end
|
||||
|
||||
it 'fails when modifying the chain' do
|
||||
expect { instance.chain = "OUTPUT" }.to raise_error(/is not supported/)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when deleting resources' do
|
||||
let(:sample_rule) {
|
||||
'-A INPUT -s 1.1.1.1 -d 1.1.1.1 -p tcp -m multiport --dports 7061,7062 -m multiport --sports 7061,7062 -j ACCEPT'
|
||||
}
|
||||
let(:resource) { provider.rule_to_hash(sample_rule, 'filter', 0) }
|
||||
let(:instance) { provider.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 'delete_args is the same as the rule string when joined' do
|
||||
expect(instance.delete_args.join(' ')).to eq(sample_rule.gsub(/\-A/,
|
||||
'-t filter -D'))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'ip6tables provider' do
|
||||
let(:provider6) { Puppet::Type.type(:firewall).provider(:ip6tables) }
|
||||
let(:resource) {
|
||||
Puppet::Type.type(:firewall).new({
|
||||
:name => '000 test foo',
|
||||
:action => 'accept',
|
||||
:provider => "ip6tables",
|
||||
})
|
||||
}
|
||||
|
||||
before :each do
|
||||
allow(Puppet::Type::Firewall).to receive(:ip6tables).and_return provider6
|
||||
allow(provider6).to receive(:command).with(:ip6tables_save).and_return "/sbin/ip6tables-save"
|
||||
|
||||
# Stub iptables version
|
||||
allow(Facter.fact(:ip6tables_version)).to receive(:value).and_return '1.4.7'
|
||||
|
||||
allow(Puppet::Util::Execution).to receive(:execute).and_return ''
|
||||
allow(Puppet::Util).to receive(:which).with("ip6tables-save").
|
||||
and_return "/sbin/ip6tables-save"
|
||||
end
|
||||
|
||||
it 'should be able to get a list of existing rules' do
|
||||
provider6.instances.each do |rule|
|
||||
rule.should be_instance_of(provider6)
|
||||
rule.properties[:provider6].to_s.should == provider6.name.to_s
|
||||
end
|
||||
end
|
||||
|
||||
it 'should ignore lines with fatal errors' do
|
||||
allow(Puppet::Util::Execution).to receive(:execute).with(['/sbin/ip6tables-save']).
|
||||
and_return("FATAL: Could not load /lib/modules/2.6.18-028stab095.1/modules.dep: No such file or directory")
|
||||
provider6.instances.length.should == 0
|
||||
end
|
||||
|
||||
# Load in ruby hash for test fixtures.
|
||||
load 'spec/fixtures/ip6tables/conversion_hash.rb'
|
||||
|
||||
describe 'when converting rules to resources' do
|
||||
ARGS_TO_HASH6.each do |test_name,data|
|
||||
describe "for test data '#{test_name}'" do
|
||||
let(:resource) { provider6.rule_to_hash(data[:line], data[:table], 0) }
|
||||
|
||||
# If this option is enabled, make sure the parameters exactly match
|
||||
if data[:compare_all] then
|
||||
it "the parameter hash keys should be the same as returned by rules_to_hash" do
|
||||
resource.keys.should =~ data[:params].keys
|
||||
end
|
||||
end
|
||||
|
||||
# Iterate across each parameter, creating an example for comparison
|
||||
data[:params].each do |param_name, param_value|
|
||||
it "the parameter '#{param_name.to_s}' should match #{param_value.inspect}" do
|
||||
resource[param_name].should == data[:params][param_name]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when working out general_args' do
|
||||
HASH_TO_ARGS6.each do |test_name,data|
|
||||
describe "for test data '#{test_name}'" do
|
||||
let(:resource) { Puppet::Type.type(:firewall).new(data[:params]) }
|
||||
let(:provider6) { Puppet::Type.type(:firewall).provider(:ip6tables) }
|
||||
let(:instance) { provider6.new(resource) }
|
||||
|
||||
it 'general_args should be valid' do
|
||||
instance.general_args.flatten.should == data[:args]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
650
modules/firewall/spec/unit/puppet/type/firewall_spec.rb
Executable file
650
modules/firewall/spec/unit/puppet/type/firewall_spec.rb
Executable file
|
@ -0,0 +1,650 @@
|
|||
#!/usr/bin/env rspec
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
firewall = Puppet::Type.type(:firewall)
|
||||
|
||||
describe firewall do
|
||||
before :each do
|
||||
@class = firewall
|
||||
@provider = double 'provider'
|
||||
allow(@provider).to receive(:name).and_return(:iptables)
|
||||
allow(Puppet::Type::Firewall).to receive(:defaultprovider).and_return @provider
|
||||
|
||||
@resource = @class.new({:name => '000 test foo'})
|
||||
|
||||
# Stub iptables version
|
||||
allow(Facter.fact(:iptables_version)).to receive(:value).and_return('1.4.2')
|
||||
allow(Facter.fact(:ip6tables_version)).to receive(:value).and_return('1.4.2')
|
||||
|
||||
# Stub confine facts
|
||||
allow(Facter.fact(:kernel)).to receive(:value).and_return('Linux')
|
||||
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return('Debian')
|
||||
end
|
||||
|
||||
it 'should have :name be its namevar' do
|
||||
@class.key_attributes.should == [:name]
|
||||
end
|
||||
|
||||
describe ':name' do
|
||||
it 'should accept a name' do
|
||||
@resource[:name] = '000-test-foo'
|
||||
@resource[:name].should == '000-test-foo'
|
||||
end
|
||||
|
||||
it 'should not accept a name with non-ASCII chars' do
|
||||
lambda { @resource[:name] = '%*#^(#$' }.should raise_error(Puppet::Error)
|
||||
end
|
||||
end
|
||||
|
||||
describe ':action' do
|
||||
it "should have no default" do
|
||||
res = @class.new(:name => "000 test")
|
||||
res.parameters[:action].should == nil
|
||||
end
|
||||
|
||||
[:accept, :drop, :reject].each do |action|
|
||||
it "should accept value #{action}" do
|
||||
@resource[:action] = action
|
||||
@resource[:action].should == action
|
||||
end
|
||||
end
|
||||
|
||||
it 'should fail when value is not recognized' do
|
||||
lambda { @resource[:action] = 'not valid' }.should raise_error(Puppet::Error)
|
||||
end
|
||||
end
|
||||
|
||||
describe ':chain' do
|
||||
[:INPUT, :FORWARD, :OUTPUT, :PREROUTING, :POSTROUTING].each do |chain|
|
||||
it "should accept chain value #{chain}" do
|
||||
@resource[:chain] = chain
|
||||
@resource[:chain].should == chain
|
||||
end
|
||||
end
|
||||
|
||||
it 'should fail when the chain value is not recognized' do
|
||||
lambda { @resource[:chain] = 'not valid' }.should raise_error(Puppet::Error)
|
||||
end
|
||||
end
|
||||
|
||||
describe ':table' do
|
||||
[:nat, :mangle, :filter, :raw].each do |table|
|
||||
it "should accept table value #{table}" do
|
||||
@resource[:table] = table
|
||||
@resource[:table].should == table
|
||||
end
|
||||
end
|
||||
|
||||
it "should fail when table value is not recognized" do
|
||||
lambda { @resource[:table] = 'not valid' }.should raise_error(Puppet::Error)
|
||||
end
|
||||
end
|
||||
|
||||
describe ':proto' do
|
||||
[:tcp, :udp, :icmp, :esp, :ah, :vrrp, :igmp, :ipencap, :ospf, :gre, :all].each do |proto|
|
||||
it "should accept proto value #{proto}" do
|
||||
@resource[:proto] = proto
|
||||
@resource[:proto].should == proto
|
||||
end
|
||||
end
|
||||
|
||||
it "should fail when proto value is not recognized" do
|
||||
lambda { @resource[:proto] = 'foo' }.should raise_error(Puppet::Error)
|
||||
end
|
||||
end
|
||||
|
||||
describe ':jump' do
|
||||
it "should have no default" do
|
||||
res = @class.new(:name => "000 test")
|
||||
res.parameters[:jump].should == nil
|
||||
end
|
||||
|
||||
['QUEUE', 'RETURN', 'DNAT', 'SNAT', 'LOG', 'MASQUERADE', 'REDIRECT', 'MARK'].each do |jump|
|
||||
it "should accept jump value #{jump}" do
|
||||
@resource[:jump] = jump
|
||||
@resource[:jump].should == jump
|
||||
end
|
||||
end
|
||||
|
||||
['ACCEPT', 'DROP', 'REJECT'].each do |jump|
|
||||
it "should now fail when value #{jump}" do
|
||||
lambda { @resource[:jump] = jump }.should raise_error(Puppet::Error)
|
||||
end
|
||||
end
|
||||
|
||||
it "should fail when jump value is not recognized" do
|
||||
lambda { @resource[:jump] = '%^&*' }.should raise_error(Puppet::Error)
|
||||
end
|
||||
end
|
||||
|
||||
[:source, :destination].each do |addr|
|
||||
describe addr do
|
||||
it "should accept a #{addr} as a string" do
|
||||
@resource[addr] = '127.0.0.1'
|
||||
@resource[addr].should == '127.0.0.1/32'
|
||||
end
|
||||
['0.0.0.0/0', '::/0'].each do |prefix|
|
||||
it "should be nil for zero prefix length address #{prefix}" do
|
||||
@resource[addr] = prefix
|
||||
@resource[addr].should == nil
|
||||
end
|
||||
end
|
||||
it "should accept a negated #{addr} as a string" do
|
||||
@resource[addr] = '! 127.0.0.1'
|
||||
@resource[addr].should == '! 127.0.0.1/32'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
[:dport, :sport].each do |port|
|
||||
describe port do
|
||||
it "should accept a #{port} as string" do
|
||||
@resource[port] = '22'
|
||||
@resource[port].should == ['22']
|
||||
end
|
||||
|
||||
it "should accept a #{port} as an array" do
|
||||
@resource[port] = ['22','23']
|
||||
@resource[port].should == ['22','23']
|
||||
end
|
||||
|
||||
it "should accept a #{port} as a number" do
|
||||
@resource[port] = 22
|
||||
@resource[port].should == ['22']
|
||||
end
|
||||
|
||||
it "should accept a #{port} as a hyphen separated range" do
|
||||
@resource[port] = ['22-1000']
|
||||
@resource[port].should == ['22-1000']
|
||||
end
|
||||
|
||||
it "should accept a #{port} as a combination of arrays of single and " \
|
||||
"hyphen separated ranges" do
|
||||
|
||||
@resource[port] = ['22-1000','33','3000-4000']
|
||||
@resource[port].should == ['22-1000','33','3000-4000']
|
||||
end
|
||||
|
||||
it "should convert a port name for #{port} to its number" do
|
||||
@resource[port] = 'ssh'
|
||||
@resource[port].should == ['22']
|
||||
end
|
||||
|
||||
it "should not accept something invalid for #{port}" do
|
||||
expect { @resource[port] = 'something odd' }.to raise_error(Puppet::Error, /^Parameter .+ failed.+Munging failed for value ".+" in class .+: no such service/)
|
||||
end
|
||||
|
||||
it "should not accept something invalid in an array for #{port}" do
|
||||
expect { @resource[port] = ['something odd','something even odder'] }.to raise_error(Puppet::Error, /^Parameter .+ failed.+Munging failed for value ".+" in class .+: no such service/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
[:dst_type, :src_type].each do |addrtype|
|
||||
describe addrtype do
|
||||
it "should have no default" do
|
||||
res = @class.new(:name => "000 test")
|
||||
res.parameters[addrtype].should == nil
|
||||
end
|
||||
end
|
||||
|
||||
[:UNSPEC, :UNICAST, :LOCAL, :BROADCAST, :ANYCAST, :MULTICAST, :BLACKHOLE,
|
||||
:UNREACHABLE, :PROHIBIT, :THROW, :NAT, :XRESOLVE].each do |type|
|
||||
it "should accept #{addrtype} value #{type}" do
|
||||
@resource[addrtype] = type
|
||||
@resource[addrtype].should == type
|
||||
end
|
||||
end
|
||||
|
||||
it "should fail when #{addrtype} value is not recognized" do
|
||||
lambda { @resource[addrtype] = 'foo' }.should raise_error(Puppet::Error)
|
||||
end
|
||||
end
|
||||
|
||||
[:iniface, :outiface].each do |iface|
|
||||
describe iface do
|
||||
it "should accept #{iface} value as a string" do
|
||||
@resource[iface] = 'eth1'
|
||||
@resource[iface].should == 'eth1'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
[:tosource, :todest].each do |addr|
|
||||
describe addr do
|
||||
it "should accept #{addr} value as a string" do
|
||||
@resource[addr] = '127.0.0.1'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe ':log_level' do
|
||||
values = {
|
||||
'panic' => '0',
|
||||
'alert' => '1',
|
||||
'crit' => '2',
|
||||
'err' => '3',
|
||||
'warn' => '4',
|
||||
'warning' => '4',
|
||||
'not' => '5',
|
||||
'notice' => '5',
|
||||
'info' => '6',
|
||||
'debug' => '7'
|
||||
}
|
||||
|
||||
values.each do |k,v|
|
||||
it {
|
||||
@resource[:log_level] = k
|
||||
@resource[:log_level].should == v
|
||||
}
|
||||
|
||||
it {
|
||||
@resource[:log_level] = 3
|
||||
@resource[:log_level].should == 3
|
||||
}
|
||||
|
||||
it { lambda { @resource[:log_level] = 'foo' }.should raise_error(Puppet::Error) }
|
||||
end
|
||||
end
|
||||
|
||||
describe ':icmp' do
|
||||
icmp_codes = {
|
||||
:iptables => {
|
||||
'0' => 'echo-reply',
|
||||
'3' => 'destination-unreachable',
|
||||
'4' => 'source-quench',
|
||||
'6' => 'redirect',
|
||||
'8' => 'echo-request',
|
||||
'9' => 'router-advertisement',
|
||||
'10' => 'router-solicitation',
|
||||
'11' => 'time-exceeded',
|
||||
'12' => 'parameter-problem',
|
||||
'13' => 'timestamp-request',
|
||||
'14' => 'timestamp-reply',
|
||||
'17' => 'address-mask-request',
|
||||
'18' => 'address-mask-reply'
|
||||
},
|
||||
:ip6tables => {
|
||||
'1' => 'destination-unreachable',
|
||||
'3' => 'time-exceeded',
|
||||
'4' => 'parameter-problem',
|
||||
'128' => 'echo-request',
|
||||
'129' => 'echo-reply',
|
||||
'133' => 'router-solicitation',
|
||||
'134' => 'router-advertisement',
|
||||
'137' => 'redirect'
|
||||
}
|
||||
}
|
||||
icmp_codes.each do |provider, values|
|
||||
describe provider do
|
||||
values.each do |k,v|
|
||||
it 'should convert icmp string to number' do
|
||||
@resource[:provider] = provider
|
||||
@resource[:provider].should == provider
|
||||
@resource[:icmp] = v
|
||||
@resource[:icmp].should == k
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'should accept values as integers' do
|
||||
@resource[:icmp] = 9
|
||||
@resource[:icmp].should == 9
|
||||
end
|
||||
|
||||
it 'should fail if icmp type is "any"' do
|
||||
lambda { @resource[:icmp] = 'any' }.should raise_error(Puppet::Error)
|
||||
end
|
||||
|
||||
it 'should fail if icmp type cannot be mapped to a numeric' do
|
||||
lambda { @resource[:icmp] = 'foo' }.should raise_error(Puppet::Error)
|
||||
end
|
||||
end
|
||||
|
||||
describe ':state' do
|
||||
it 'should accept value as a string' do
|
||||
@resource[:state] = :INVALID
|
||||
@resource[:state].should == [:INVALID]
|
||||
end
|
||||
|
||||
it 'should accept value as an array' do
|
||||
@resource[:state] = [:INVALID, :NEW]
|
||||
@resource[:state].should == [:INVALID, :NEW]
|
||||
end
|
||||
|
||||
it 'should sort values alphabetically' do
|
||||
@resource[:state] = [:NEW, :ESTABLISHED]
|
||||
@resource[:state].should == [:ESTABLISHED, :NEW]
|
||||
end
|
||||
end
|
||||
|
||||
describe ':ctstate' do
|
||||
it 'should accept value as a string' do
|
||||
@resource[:ctstate] = :INVALID
|
||||
@resource[:ctstate].should == [:INVALID]
|
||||
end
|
||||
|
||||
it 'should accept value as an array' do
|
||||
@resource[:ctstate] = [:INVALID, :NEW]
|
||||
@resource[:ctstate].should == [:INVALID, :NEW]
|
||||
end
|
||||
|
||||
it 'should sort values alphabetically' do
|
||||
@resource[:ctstate] = [:NEW, :ESTABLISHED]
|
||||
@resource[:ctstate].should == [:ESTABLISHED, :NEW]
|
||||
end
|
||||
end
|
||||
|
||||
describe ':burst' do
|
||||
it 'should accept numeric values' do
|
||||
@resource[:burst] = 12
|
||||
@resource[:burst].should == 12
|
||||
end
|
||||
|
||||
it 'should fail if value is not numeric' do
|
||||
lambda { @resource[:burst] = 'foo' }.should raise_error(Puppet::Error)
|
||||
end
|
||||
end
|
||||
|
||||
describe ':recent' do
|
||||
['set', 'update', 'rcheck', 'remove'].each do |recent|
|
||||
it "should accept recent value #{recent}" do
|
||||
@resource[:recent] = recent
|
||||
@resource[:recent].should == "--#{recent}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe ':action and :jump' do
|
||||
it 'should allow only 1 to be set at a time' do
|
||||
expect {
|
||||
@class.new(
|
||||
:name => "001-test",
|
||||
:action => "accept",
|
||||
:jump => "custom_chain"
|
||||
)
|
||||
}.to raise_error(Puppet::Error, /Only one of the parameters 'action' and 'jump' can be set$/)
|
||||
end
|
||||
end
|
||||
describe ':gid and :uid' do
|
||||
it 'should allow me to set uid' do
|
||||
@resource[:uid] = 'root'
|
||||
@resource[:uid].should == 'root'
|
||||
end
|
||||
it 'should allow me to set uid as an array, and silently hide my error' do
|
||||
@resource[:uid] = ['root', 'bobby']
|
||||
@resource[:uid].should == 'root'
|
||||
end
|
||||
it 'should allow me to set gid' do
|
||||
@resource[:gid] = 'root'
|
||||
@resource[:gid].should == 'root'
|
||||
end
|
||||
it 'should allow me to set gid as an array, and silently hide my error' do
|
||||
@resource[:gid] = ['root', 'bobby']
|
||||
@resource[:gid].should == 'root'
|
||||
end
|
||||
end
|
||||
|
||||
describe ':set_mark' do
|
||||
['1.3.2', '1.4.2'].each do |iptables_version|
|
||||
describe "with iptables #{iptables_version}" do
|
||||
before {
|
||||
Facter.clear
|
||||
allow(Facter.fact(:iptables_version)).to receive(:value).and_return iptables_version
|
||||
allow(Facter.fact(:ip6tables_version)).to receive(:value).and_return iptables_version
|
||||
}
|
||||
|
||||
if iptables_version == '1.3.2'
|
||||
it 'should allow me to set set-mark without mask' do
|
||||
@resource[:set_mark] = '0x3e8'
|
||||
@resource[:set_mark].should == '0x3e8'
|
||||
end
|
||||
it 'should convert int to hex without mask' do
|
||||
@resource[:set_mark] = '1000'
|
||||
@resource[:set_mark].should == '0x3e8'
|
||||
end
|
||||
it 'should fail if mask is present' do
|
||||
lambda { @resource[:set_mark] = '0x3e8/0xffffffff'}.should raise_error(
|
||||
Puppet::Error, /iptables version #{iptables_version} does not support masks on MARK rules$/
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
if iptables_version == '1.4.2'
|
||||
it 'should allow me to set set-mark with mask' do
|
||||
@resource[:set_mark] = '0x3e8/0xffffffff'
|
||||
@resource[:set_mark].should == '0x3e8/0xffffffff'
|
||||
end
|
||||
it 'should convert int to hex and add a 32 bit mask' do
|
||||
@resource[:set_mark] = '1000'
|
||||
@resource[:set_mark].should == '0x3e8/0xffffffff'
|
||||
end
|
||||
it 'should add a 32 bit mask' do
|
||||
@resource[:set_mark] = '0x32'
|
||||
@resource[:set_mark].should == '0x32/0xffffffff'
|
||||
end
|
||||
it 'should use the mask provided' do
|
||||
@resource[:set_mark] = '0x32/0x4'
|
||||
@resource[:set_mark].should == '0x32/0x4'
|
||||
end
|
||||
it 'should use the mask provided and convert int to hex' do
|
||||
@resource[:set_mark] = '1000/0x4'
|
||||
@resource[:set_mark].should == '0x3e8/0x4'
|
||||
end
|
||||
it 'should fail if mask value is more than 32 bits' do
|
||||
lambda { @resource[:set_mark] = '1/4294967296'}.should raise_error(
|
||||
Puppet::Error, /MARK mask must be integer or hex between 0 and 0xffffffff$/
|
||||
)
|
||||
end
|
||||
it 'should fail if mask is malformed' do
|
||||
lambda { @resource[:set_mark] = '1000/0xq4'}.should raise_error(
|
||||
Puppet::Error, /MARK mask must be integer or hex between 0 and 0xffffffff$/
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
['/', '1000/', 'pwnie'].each do |bad_mark|
|
||||
it "should fail with malformed mark '#{bad_mark}'" do
|
||||
lambda { @resource[:set_mark] = bad_mark}.should raise_error(Puppet::Error)
|
||||
end
|
||||
end
|
||||
it 'should fail if mark value is more than 32 bits' do
|
||||
lambda { @resource[:set_mark] = '4294967296'}.should raise_error(
|
||||
Puppet::Error, /MARK value must be integer or hex between 0 and 0xffffffff$/
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
[:chain, :jump].each do |param|
|
||||
describe param do
|
||||
it 'should autorequire fwchain when table and provider are undefined' do
|
||||
@resource[param] = 'FOO'
|
||||
@resource[:table].should == :filter
|
||||
@resource[:provider].should == :iptables
|
||||
|
||||
chain = Puppet::Type.type(:firewallchain).new(:name => 'FOO:filter:IPv4')
|
||||
catalog = Puppet::Resource::Catalog.new
|
||||
catalog.add_resource @resource
|
||||
catalog.add_resource chain
|
||||
rel = @resource.autorequire[0]
|
||||
rel.source.ref.should == chain.ref
|
||||
rel.target.ref.should == @resource.ref
|
||||
end
|
||||
|
||||
it 'should autorequire fwchain when table is undefined and provider is ip6tables' do
|
||||
@resource[param] = 'FOO'
|
||||
@resource[:table].should == :filter
|
||||
@resource[:provider] = :ip6tables
|
||||
|
||||
chain = Puppet::Type.type(:firewallchain).new(:name => 'FOO:filter:IPv6')
|
||||
catalog = Puppet::Resource::Catalog.new
|
||||
catalog.add_resource @resource
|
||||
catalog.add_resource chain
|
||||
rel = @resource.autorequire[0]
|
||||
rel.source.ref.should == chain.ref
|
||||
rel.target.ref.should == @resource.ref
|
||||
end
|
||||
|
||||
it 'should autorequire fwchain when table is raw and provider is undefined' do
|
||||
@resource[param] = 'FOO'
|
||||
@resource[:table] = :raw
|
||||
@resource[:provider].should == :iptables
|
||||
|
||||
chain = Puppet::Type.type(:firewallchain).new(:name => 'FOO:raw:IPv4')
|
||||
catalog = Puppet::Resource::Catalog.new
|
||||
catalog.add_resource @resource
|
||||
catalog.add_resource chain
|
||||
rel = @resource.autorequire[0]
|
||||
rel.source.ref.should == chain.ref
|
||||
rel.target.ref.should == @resource.ref
|
||||
end
|
||||
|
||||
it 'should autorequire fwchain when table is raw and provider is ip6tables' do
|
||||
@resource[param] = 'FOO'
|
||||
@resource[:table] = :raw
|
||||
@resource[:provider] = :ip6tables
|
||||
|
||||
chain = Puppet::Type.type(:firewallchain).new(:name => 'FOO:raw:IPv6')
|
||||
catalog = Puppet::Resource::Catalog.new
|
||||
catalog.add_resource @resource
|
||||
catalog.add_resource chain
|
||||
rel = @resource.autorequire[0]
|
||||
rel.source.ref.should == chain.ref
|
||||
rel.target.ref.should == @resource.ref
|
||||
end
|
||||
|
||||
# test where autorequire is still needed (table != filter)
|
||||
['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
|
||||
@resource[:provider].should == :iptables
|
||||
|
||||
chain = Puppet::Type.type(:firewallchain).new(:name => "#{test_chain}:mangle:IPv4")
|
||||
catalog = Puppet::Resource::Catalog.new
|
||||
catalog.add_resource @resource
|
||||
catalog.add_resource chain
|
||||
rel = @resource.autorequire[0]
|
||||
rel.source.ref.should == chain.ref
|
||||
rel.target.ref.should == @resource.ref
|
||||
end
|
||||
|
||||
it "should autorequire fwchain #{test_chain} when table is mangle and provider is ip6tables" do
|
||||
@resource[param] = test_chain
|
||||
@resource[:table] = :mangle
|
||||
@resource[:provider] = :ip6tables
|
||||
|
||||
chain = Puppet::Type.type(:firewallchain).new(:name => "#{test_chain}:mangle:IPv6")
|
||||
catalog = Puppet::Resource::Catalog.new
|
||||
catalog.add_resource @resource
|
||||
catalog.add_resource chain
|
||||
rel = @resource.autorequire[0]
|
||||
rel.source.ref.should == chain.ref
|
||||
rel.target.ref.should == @resource.ref
|
||||
end
|
||||
end
|
||||
|
||||
# test of case where autorequire should not happen
|
||||
['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
|
||||
@resource[:table].should == :filter
|
||||
@resource[:provider].should == :iptables
|
||||
|
||||
chain = Puppet::Type.type(:firewallchain).new(:name => "#{test_chain}:filter:IPv4")
|
||||
catalog = Puppet::Resource::Catalog.new
|
||||
catalog.add_resource @resource
|
||||
catalog.add_resource chain
|
||||
rel = @resource.autorequire[0]
|
||||
rel.should == nil
|
||||
end
|
||||
|
||||
it "should not autorequire fwchain #{test_chain} when table is undefined and provider is ip6tables" do
|
||||
@resource[param] = test_chain
|
||||
@resource[:table].should == :filter
|
||||
@resource[:provider] = :ip6tables
|
||||
|
||||
chain = Puppet::Type.type(:firewallchain).new(:name => "#{test_chain}:filter:IPv6")
|
||||
catalog = Puppet::Resource::Catalog.new
|
||||
catalog.add_resource @resource
|
||||
catalog.add_resource chain
|
||||
rel = @resource.autorequire[0]
|
||||
rel.should == nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe ":chain and :jump" do
|
||||
it 'should autorequire independent fwchains' do
|
||||
@resource[:chain] = 'FOO'
|
||||
@resource[:jump] = 'BAR'
|
||||
@resource[:table].should == :filter
|
||||
@resource[:provider].should == :iptables
|
||||
|
||||
chain_foo = Puppet::Type.type(:firewallchain).new(:name => 'FOO:filter:IPv4')
|
||||
chain_bar = Puppet::Type.type(:firewallchain).new(:name => 'BAR:filter:IPv4')
|
||||
catalog = Puppet::Resource::Catalog.new
|
||||
catalog.add_resource @resource
|
||||
catalog.add_resource chain_foo
|
||||
catalog.add_resource chain_bar
|
||||
rel = @resource.autorequire
|
||||
rel[0].source.ref.should == chain_foo.ref
|
||||
rel[0].target.ref.should == @resource.ref
|
||||
rel[1].source.ref.should == chain_bar.ref
|
||||
rel[1].target.ref.should == @resource.ref
|
||||
end
|
||||
end
|
||||
|
||||
describe ':pkttype' do
|
||||
[:multicast, :broadcast, :unicast].each do |pkttype|
|
||||
it "should accept pkttype value #{pkttype}" do
|
||||
@resource[:pkttype] = pkttype
|
||||
@resource[:pkttype].should == pkttype
|
||||
end
|
||||
end
|
||||
|
||||
it 'should fail when the pkttype value is not recognized' do
|
||||
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
|
185
modules/firewall/spec/unit/puppet/type/firewallchain_spec.rb
Executable file
185
modules/firewall/spec/unit/puppet/type/firewallchain_spec.rb
Executable file
|
@ -0,0 +1,185 @@
|
|||
#!/usr/bin/env rspec
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
firewallchain = Puppet::Type.type(:firewallchain)
|
||||
|
||||
describe firewallchain do
|
||||
before(:each) do
|
||||
# Stub confine facts
|
||||
allow(Facter.fact(:kernel)).to receive(:value).and_return('Linux')
|
||||
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return('Debian')
|
||||
end
|
||||
let(:klass) { firewallchain }
|
||||
let(:provider) {
|
||||
prov = double 'provider'
|
||||
allow(prov).to receive(:name).and_return(:iptables_chain)
|
||||
prov
|
||||
}
|
||||
let(:resource) {
|
||||
allow(Puppet::Type::Firewallchain).to receive(:defaultprovider).and_return provider
|
||||
klass.new({:name => 'INPUT:filter:IPv4', :policy => :accept })
|
||||
}
|
||||
|
||||
it 'should have :name be its namevar' do
|
||||
klass.key_attributes.should == [:name]
|
||||
end
|
||||
|
||||
describe ':name' do
|
||||
{'nat' => ['PREROUTING', 'POSTROUTING', 'INPUT', 'OUTPUT'],
|
||||
'mangle' => [ 'PREROUTING', 'POSTROUTING', 'INPUT', 'FORWARD', 'OUTPUT' ],
|
||||
'filter' => ['INPUT','OUTPUT','FORWARD'],
|
||||
'raw' => [ 'PREROUTING', 'OUTPUT'],
|
||||
'broute' => ['BROUTING']
|
||||
}.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
|
||||
expect { resource[:name] = name }.to raise_error(Puppet::Error)
|
||||
end
|
||||
elsif protocol != 'ethernet' && table == 'broute'
|
||||
it "should fail #{name}" do
|
||||
expect { resource[:name] = name }.to raise_error(Puppet::Error)
|
||||
end
|
||||
else
|
||||
it "should accept name #{name}" do
|
||||
resource[:name] = name
|
||||
resource[:name].should == name
|
||||
end
|
||||
end
|
||||
end # chainname
|
||||
end # protocol
|
||||
|
||||
[ 'PREROUTING', 'POSTROUTING', 'BROUTING', 'INPUT', 'FORWARD', 'OUTPUT' ].each do |internalchain|
|
||||
name = internalchain + ':' + table + ':'
|
||||
if internalchain == 'BROUTING'
|
||||
name += 'ethernet'
|
||||
elsif table == 'nat'
|
||||
name += 'IPv4'
|
||||
else
|
||||
name += 'IPv4'
|
||||
end
|
||||
if allowedinternalchains.include? internalchain
|
||||
it "should allow #{name}" do
|
||||
resource[:name] = name
|
||||
resource[:name].should == name
|
||||
end
|
||||
else
|
||||
it "should fail #{name}" do
|
||||
expect { resource[:name] = name }.to raise_error(Puppet::Error)
|
||||
end
|
||||
end
|
||||
end # internalchain
|
||||
|
||||
end # table, allowedinternalchainnames
|
||||
|
||||
it 'should fail with invalid table names' do
|
||||
expect { resource[:name] = 'wrongtablename:test:IPv4' }.to raise_error(Puppet::Error)
|
||||
end
|
||||
|
||||
it 'should fail with invalid protocols names' do
|
||||
expect { resource[:name] = 'test:filter:IPv5' }.to raise_error(Puppet::Error)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe ':policy' do
|
||||
|
||||
[:accept, :drop, :queue, :return].each do |policy|
|
||||
it "should accept policy #{policy}" do
|
||||
resource[:policy] = policy
|
||||
resource[:policy].should == policy
|
||||
end
|
||||
end
|
||||
|
||||
it 'should fail when value is not recognized' do
|
||||
expect { resource[:policy] = 'not valid' }.to raise_error(Puppet::Error)
|
||||
end
|
||||
|
||||
[:accept, :drop, :queue, :return].each do |policy|
|
||||
it "non-inbuilt chains should not accept policy #{policy}" do
|
||||
expect { klass.new({:name => 'testchain:filter:IPv4', :policy => policy }) }.to raise_error(Puppet::Error)
|
||||
end
|
||||
it "non-inbuilt chains can accept policies on protocol = ethernet (policy #{policy})" do
|
||||
klass.new({:name => 'testchain:filter:ethernet', :policy => policy })
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
describe 'purge iptables rules' do
|
||||
before(:each) do
|
||||
allow(Puppet::Type.type(:firewall).provider(:iptables)).to receive(:iptables_save).and_return(<<EOS
|
||||
# Completed on Sun Jan 5 19:30:21 2014
|
||||
# Generated by iptables-save v1.4.12 on Sun Jan 5 19:30:21 2014
|
||||
*filter
|
||||
:INPUT DROP [0:0]
|
||||
:FORWARD DROP [0:0]
|
||||
:OUTPUT ACCEPT [0:0]
|
||||
:LOCAL_FORWARD - [0:0]
|
||||
:LOCAL_FORWARD_PRE - [0:0]
|
||||
:LOCAL_INPUT - [0:0]
|
||||
:LOCAL_INPUT_PRE - [0:0]
|
||||
:fail2ban-ssh - [0:0]
|
||||
-A INPUT -p tcp -m multiport --dports 22 -j fail2ban-ssh
|
||||
-A INPUT -i lo -m comment --comment "012 accept loopback" -j ACCEPT
|
||||
-A INPUT -p tcp -m multiport --dports 22 -m comment --comment "020 ssh" -j ACCEPT
|
||||
-A OUTPUT -d 1.2.1.2 -j DROP
|
||||
-A fail2ban-ssh -j RETURN
|
||||
COMMIT
|
||||
# Completed on Sun Jan 5 19:30:21 2014
|
||||
EOS
|
||||
)
|
||||
end
|
||||
|
||||
it 'should generate iptables resources' do
|
||||
resource = Puppet::Type::Firewallchain.new(:name => 'INPUT:filter:IPv4', :purge => true)
|
||||
|
||||
expect(resource.generate.size).to eq(3)
|
||||
end
|
||||
|
||||
it 'should not generate ignored iptables rules' do
|
||||
resource = Puppet::Type::Firewallchain.new(:name => 'INPUT:filter:IPv4', :purge => true, :ignore => ['-j fail2ban-ssh'])
|
||||
|
||||
expect(resource.generate.size).to eq(2)
|
||||
end
|
||||
|
||||
it 'should not generate iptables resources when not enabled' do
|
||||
resource = Puppet::Type::Firewallchain.new(:name => 'INPUT:filter:IPv4')
|
||||
|
||||
expect(resource.generate.size).to eq(0)
|
||||
end
|
||||
end
|
||||
end
|
197
modules/firewall/spec/unit/puppet/util/firewall_spec.rb
Normal file
197
modules/firewall/spec/unit/puppet/util/firewall_spec.rb
Normal file
|
@ -0,0 +1,197 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'Puppet::Util::Firewall' do
|
||||
let(:resource) {
|
||||
type = Puppet::Type.type(:firewall)
|
||||
provider = double 'provider'
|
||||
allow(provider).to receive(:name).and_return(:iptables)
|
||||
allow(Puppet::Type::Firewall).to receive(:defaultprovider).and_return(provider)
|
||||
type.new({:name => '000 test foo'})
|
||||
}
|
||||
|
||||
before(:each) { resource }
|
||||
|
||||
describe '#host_to_ip' do
|
||||
subject { resource }
|
||||
specify {
|
||||
expect(Resolv).to receive(:getaddress).with('puppetlabs.com').and_return('96.126.112.51')
|
||||
subject.host_to_ip('puppetlabs.com').should == '96.126.112.51/32'
|
||||
}
|
||||
specify { subject.host_to_ip('96.126.112.51').should == '96.126.112.51/32' }
|
||||
specify { subject.host_to_ip('96.126.112.51/32').should == '96.126.112.51/32' }
|
||||
specify { subject.host_to_ip('2001:db8:85a3:0:0:8a2e:370:7334').should == '2001:db8:85a3::8a2e:370:7334/128' }
|
||||
specify { subject.host_to_ip('2001:db8:1234::/48').should == '2001:db8:1234::/48' }
|
||||
specify { subject.host_to_ip('0.0.0.0/0').should == nil }
|
||||
specify { subject.host_to_ip('::/0').should == nil }
|
||||
end
|
||||
|
||||
describe '#host_to_mask' do
|
||||
subject { resource }
|
||||
specify {
|
||||
expect(Resolv).to receive(:getaddress).at_least(:once).with('puppetlabs.com').and_return('96.126.112.51')
|
||||
subject.host_to_mask('puppetlabs.com').should == '96.126.112.51/32'
|
||||
subject.host_to_mask('!puppetlabs.com').should == '! 96.126.112.51/32'
|
||||
}
|
||||
specify { subject.host_to_mask('96.126.112.51').should == '96.126.112.51/32' }
|
||||
specify { subject.host_to_mask('!96.126.112.51').should == '! 96.126.112.51/32' }
|
||||
specify { subject.host_to_mask('96.126.112.51/32').should == '96.126.112.51/32' }
|
||||
specify { subject.host_to_mask('! 96.126.112.51/32').should == '! 96.126.112.51/32' }
|
||||
specify { subject.host_to_mask('2001:db8:85a3:0:0:8a2e:370:7334').should == '2001:db8:85a3::8a2e:370:7334/128' }
|
||||
specify { subject.host_to_mask('!2001:db8:85a3:0:0:8a2e:370:7334').should == '! 2001:db8:85a3::8a2e:370:7334/128' }
|
||||
specify { subject.host_to_mask('2001:db8:1234::/48').should == '2001:db8:1234::/48' }
|
||||
specify { subject.host_to_mask('! 2001:db8:1234::/48').should == '! 2001:db8:1234::/48' }
|
||||
specify { subject.host_to_mask('0.0.0.0/0').should == nil }
|
||||
specify { subject.host_to_mask('!0.0.0.0/0').should == nil }
|
||||
specify { subject.host_to_mask('::/0').should == nil }
|
||||
specify { subject.host_to_mask('! ::/0').should == nil }
|
||||
end
|
||||
|
||||
describe '#icmp_name_to_number' do
|
||||
describe 'proto unsupported' do
|
||||
subject { resource }
|
||||
|
||||
%w{inet5 inet8 foo}.each do |proto|
|
||||
it "should reject invalid proto #{proto}" do
|
||||
expect { subject.icmp_name_to_number('echo-reply', proto) }.
|
||||
to raise_error(ArgumentError, "unsupported protocol family '#{proto}'")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'proto IPv4' do
|
||||
proto = 'inet'
|
||||
subject { resource }
|
||||
specify { subject.icmp_name_to_number('echo-reply', proto).should == '0' }
|
||||
specify { subject.icmp_name_to_number('destination-unreachable', proto).should == '3' }
|
||||
specify { subject.icmp_name_to_number('source-quench', proto).should == '4' }
|
||||
specify { subject.icmp_name_to_number('redirect', proto).should == '6' }
|
||||
specify { subject.icmp_name_to_number('echo-request', proto).should == '8' }
|
||||
specify { subject.icmp_name_to_number('router-advertisement', proto).should == '9' }
|
||||
specify { subject.icmp_name_to_number('router-solicitation', proto).should == '10' }
|
||||
specify { subject.icmp_name_to_number('time-exceeded', proto).should == '11' }
|
||||
specify { subject.icmp_name_to_number('parameter-problem', proto).should == '12' }
|
||||
specify { subject.icmp_name_to_number('timestamp-request', proto).should == '13' }
|
||||
specify { subject.icmp_name_to_number('timestamp-reply', proto).should == '14' }
|
||||
specify { subject.icmp_name_to_number('address-mask-request', proto).should == '17' }
|
||||
specify { subject.icmp_name_to_number('address-mask-reply', proto).should == '18' }
|
||||
end
|
||||
|
||||
describe 'proto IPv6' do
|
||||
proto = 'inet6'
|
||||
subject { resource }
|
||||
specify { subject.icmp_name_to_number('destination-unreachable', proto).should == '1' }
|
||||
specify { subject.icmp_name_to_number('time-exceeded', proto).should == '3' }
|
||||
specify { subject.icmp_name_to_number('parameter-problem', proto).should == '4' }
|
||||
specify { subject.icmp_name_to_number('echo-request', proto).should == '128' }
|
||||
specify { subject.icmp_name_to_number('echo-reply', proto).should == '129' }
|
||||
specify { subject.icmp_name_to_number('router-solicitation', proto).should == '133' }
|
||||
specify { subject.icmp_name_to_number('router-advertisement', proto).should == '134' }
|
||||
specify { subject.icmp_name_to_number('redirect', proto).should == '137' }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#string_to_port' do
|
||||
subject { resource }
|
||||
specify { subject.string_to_port('80','tcp').should == '80' }
|
||||
specify { subject.string_to_port(80,'tcp').should == '80' }
|
||||
specify { subject.string_to_port('http','tcp').should == '80' }
|
||||
specify { subject.string_to_port('domain','udp').should == '53' }
|
||||
end
|
||||
|
||||
describe '#to_hex32' do
|
||||
subject { resource }
|
||||
specify { subject.to_hex32('0').should == '0x0' }
|
||||
specify { subject.to_hex32('0x32').should == '0x32' }
|
||||
specify { subject.to_hex32('42').should == '0x2a' }
|
||||
specify { subject.to_hex32('4294967295').should == '0xffffffff' }
|
||||
specify { subject.to_hex32('4294967296').should == nil }
|
||||
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 /sbin/service if running RHEL 6 or earlier' do
|
||||
allow(Facter.fact(:osfamily)).to receive(:value).and_return('RedHat')
|
||||
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return('RedHat')
|
||||
allow(Facter.fact(:operatingsystemrelease)).to receive(:value).and_return('6')
|
||||
|
||||
expect(subject).to receive(:execute).with(%w{/sbin/service iptables save})
|
||||
subject.persist_iptables(proto)
|
||||
end
|
||||
|
||||
it 'should exec for systemd if running RHEL 7 or greater' do
|
||||
allow(Facter.fact(:osfamily)).to receive(:value).and_return('RedHat')
|
||||
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return('RedHat')
|
||||
allow(Facter.fact(:operatingsystemrelease)).to receive(:value).and_return('7')
|
||||
|
||||
expect(subject).to receive(:execute).with(%w{/usr/libexec/iptables/iptables.init save})
|
||||
subject.persist_iptables(proto)
|
||||
end
|
||||
|
||||
it 'should exec for systemd if running Fedora 15 or greater' do
|
||||
allow(Facter.fact(:osfamily)).to receive(:value).and_return('RedHat')
|
||||
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return('Fedora')
|
||||
allow(Facter.fact(:operatingsystemrelease)).to receive(:value).and_return('15')
|
||||
|
||||
expect(subject).to receive(:execute).with(%w{/usr/libexec/iptables/iptables.init save})
|
||||
subject.persist_iptables(proto)
|
||||
end
|
||||
|
||||
it 'should exec for CentOS identified from operatingsystem' do
|
||||
allow(Facter.fact(:osfamily)).to receive(:value).and_return(nil)
|
||||
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return('CentOS')
|
||||
expect(subject).to receive(:execute).with(%w{/sbin/service iptables save})
|
||||
subject.persist_iptables(proto)
|
||||
end
|
||||
|
||||
it 'should exec for Archlinux identified from osfamily' do
|
||||
allow(Facter.fact(:osfamily)).to receive(:value).and_return('Archlinux')
|
||||
expect(subject).to receive(:execute).with(['/bin/sh', '-c', '/usr/sbin/iptables-save > /etc/iptables/iptables.rules'])
|
||||
subject.persist_iptables(proto)
|
||||
end
|
||||
|
||||
it 'should raise a warning when exec fails' do
|
||||
allow(Facter.fact(:osfamily)).to receive(:value).and_return('RedHat')
|
||||
allow(Facter.fact(:operatingsystem)).to receive(:value).and_return('RedHat')
|
||||
allow(Facter.fact(:operatingsystemrelease)).to receive(:value).and_return('6')
|
||||
|
||||
expect(subject).to receive(:execute).with(%w{/sbin/service iptables save}).
|
||||
and_raise(Puppet::ExecutionFailure, 'some error')
|
||||
expect(subject).to receive(: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
|
||||
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')
|
||||
expect(subject).to receive(: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
|
||||
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.0.20090701')
|
||||
expect(subject).to receive(:execute).never
|
||||
subject.persist_iptables(proto)
|
||||
end
|
||||
|
||||
it 'should not exec for Suse which is not supported' do
|
||||
allow(Facter.fact(:osfamily)).to receive(:value).and_return('Suse')
|
||||
expect(subject).to receive(:execute).never
|
||||
subject.persist_iptables(proto)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
67
modules/firewall/spec/unit/puppet/util/ipcidr_spec.rb
Normal file
67
modules/firewall/spec/unit/puppet/util/ipcidr_spec.rb
Normal file
|
@ -0,0 +1,67 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'Puppet::Util::IPCidr' do
|
||||
describe 'ipv4 address' do
|
||||
before { @ipaddr = Puppet::Util::IPCidr.new('96.126.112.51') }
|
||||
subject { @ipaddr }
|
||||
specify { subject.cidr.should == '96.126.112.51/32' }
|
||||
specify { subject.prefixlen.should == 32 }
|
||||
specify { subject.netmask.should == '255.255.255.255' }
|
||||
end
|
||||
|
||||
describe 'single ipv4 address with cidr' do
|
||||
before { @ipcidr = Puppet::Util::IPCidr.new('96.126.112.51/32') }
|
||||
subject { @ipcidr }
|
||||
specify { subject.cidr.should == '96.126.112.51/32' }
|
||||
specify { subject.prefixlen.should == 32 }
|
||||
specify { subject.netmask.should == '255.255.255.255' }
|
||||
end
|
||||
|
||||
describe 'ipv4 address range with cidr' do
|
||||
before { @ipcidr = Puppet::Util::IPCidr.new('96.126.112.0/24') }
|
||||
subject { @ipcidr }
|
||||
specify { subject.cidr.should == '96.126.112.0/24' }
|
||||
specify { subject.prefixlen.should == 24 }
|
||||
specify { subject.netmask.should == '255.255.255.0' }
|
||||
end
|
||||
|
||||
describe 'ipv4 open range with cidr' do
|
||||
before { @ipcidr = Puppet::Util::IPCidr.new('0.0.0.0/0') }
|
||||
subject { @ipcidr }
|
||||
specify { subject.cidr.should == '0.0.0.0/0' }
|
||||
specify { subject.prefixlen.should == 0 }
|
||||
specify { subject.netmask.should == '0.0.0.0' }
|
||||
end
|
||||
|
||||
describe 'ipv6 address' do
|
||||
before { @ipaddr = Puppet::Util::IPCidr.new('2001:db8:85a3:0:0:8a2e:370:7334') }
|
||||
subject { @ipaddr }
|
||||
specify { subject.cidr.should == '2001:db8:85a3::8a2e:370:7334/128' }
|
||||
specify { subject.prefixlen.should == 128 }
|
||||
specify { subject.netmask.should == 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' }
|
||||
end
|
||||
|
||||
describe 'single ipv6 addr with cidr' do
|
||||
before { @ipaddr = Puppet::Util::IPCidr.new('2001:db8:85a3:0:0:8a2e:370:7334/128') }
|
||||
subject { @ipaddr }
|
||||
specify { subject.cidr.should == '2001:db8:85a3::8a2e:370:7334/128' }
|
||||
specify { subject.prefixlen.should == 128 }
|
||||
specify { subject.netmask.should == 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' }
|
||||
end
|
||||
|
||||
describe 'ipv6 addr range with cidr' do
|
||||
before { @ipaddr = Puppet::Util::IPCidr.new('2001:db8:1234::/48') }
|
||||
subject { @ipaddr }
|
||||
specify { subject.cidr.should == '2001:db8:1234::/48' }
|
||||
specify { subject.prefixlen.should == 48 }
|
||||
specify { subject.netmask.should == 'ffff:ffff:ffff:0000:0000:0000:0000:0000' }
|
||||
end
|
||||
|
||||
describe 'ipv6 open range with cidr' do
|
||||
before { @ipaddr = Puppet::Util::IPCidr.new('::/0') }
|
||||
subject { @ipaddr }
|
||||
specify { subject.cidr.should == '::/0' }
|
||||
specify { subject.prefixlen.should == 0 }
|
||||
specify { subject.netmask.should == '0000:0000:0000:0000:0000:0000:0000:0000' }
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue