gem 'serverspec', :require => false
gem 'beaker-rspec', :require => false
gem 'puppet-lint', :require => false
+ gem 'pry', :require => false
end
if puppetversion = ENV['PUPPET_GEM_VERSION']
# No rules at all? Just bail now.
return 1 if rules.empty?
+ # Add our rule to the end of the array of known rules
my_rule = resource[:name].to_s
rules << my_rule
- rules.sort.index(my_rule) + 1
+
+ # Find if this is a new rule or an existing rule, then find how many
+ # unmanaged rules preceed it.
+ if rules.length == rules.uniq.length
+ # This is a new rule so find its ordered location.
+ new_rule_location = rules.sort.uniq.index(my_rule)
+ if new_rule_location == 0
+ # The rule will be the first rule in the chain because nothing came
+ # before it.
+ offset_rule = rules[0]
+ else
+ # This rule will come after other managed rules, so find the rule
+ # immediately preceeding it.
+ offset_rule = rules.sort.uniq[new_rule_location - 1]
+ end
+ else
+ # This is a pre-existing rule, so find the offset from the original
+ # ordering.
+ offset_rule = my_rule
+ end
+ # Count how many unmanaged rules are ahead of the target rule so we know
+ # how much to add to the insert order
+ unnamed_offset = rules[0..rules.index(offset_rule)].inject(0) do |sum,rule|
+ # This regex matches the names given to unmanaged rules (a number
+ # 9000-9999 followed by an MD5 hash).
+ sum + (rule.match(/^9[0-9]{3}\s[a-f0-9]{32}$/) ? 1 : 0)
+ end
+
+ # Insert our new or updated rule in the correct order of named rules, but
+ # offset for unnamed rules.
+ rules.sort.index(my_rule) + 1 + unnamed_offset
end
end
--- /dev/null
+require 'spec_helper_acceptance'
+
+describe 'firewall type' 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 'contains the changable 8.0.0.1 rule' do
+ shell('iptables -S') 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 -S') 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 'adds a unmanaged rule without a comment' do
+ shell('/sbin/iptables -R INPUT 1 -t filter -s 8.0.0.3/32 -p tcp -m multiport --ports 100 -j ACCEPT')
+ expect(shell('iptables -S').stdout).to match(/-A INPUT -s 8\.0\.0\.3\/32 -p tcp -m multiport --ports 100 -j ACCEPT/)
+ 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 -S') 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 -S') 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 -S') 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
centos-59-x64:
roles:
- master
- platform: centos-59-x64
+ 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
--- /dev/null
+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
--- /dev/null
+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
centos-64-x64:
roles:
- master
- platform: el-6-i386
+ 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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
ubuntu-server-12042-x64:
roles:
- master
- platform: ubuntu-server-12.04-amd64
+ 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
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 an unname rule' 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 -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.5/32 -p tcp -m multiport --ports 400 -j ACCEPT',
+ '-A INPUT -s 8.0.0.6/32 -p tcp -m multiport --ports 500 -m comment --comment "500 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 unnamed rules' 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 between unnamed rules' 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
+ it 'understands offsets for adding rules after unnamed rules' do
+ resource = Puppet::Type.type(:firewall).new({ :name => '501 test', })
+ allow(resource.provider.class).to receive(:instances).and_return(providers)
+ expect(resource.provider.insert_order).to eq(6)
+ end
+ it 'understands offsets for editing rules after unnamed rules' do
+ resource = Puppet::Type.type(:firewall).new({ :name => '500 test', })
+ allow(resource.provider.class).to receive(:instances).and_return(providers)
+ expect(resource.provider.insert_order).to eq(5)
+ end
+ end
+ end
+
# Load in ruby hash for test fixtures.
load 'spec/fixtures/iptables/conversion_hash.rb'