From 05e50da8cbaf6b449b7b89aad6c2d4a7f469af14 Mon Sep 17 00:00:00 2001 From: Chuck Schweizer Date: Sat, 7 Mar 2015 18:32:36 -0600 Subject: [PATCH] add match_mark --- README.markdown | 2 + lib/puppet/provider/firewall/ip6tables.rb | 3 +- lib/puppet/provider/firewall/iptables.rb | 3 +- lib/puppet/type/firewall.rb | 30 +++++++++++++ spec/acceptance/match_mark_spec.rb | 53 +++++++++++++++++++++++ spec/fixtures/iptables/conversion_hash.rb | 23 ++++++++++ 6 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 spec/acceptance/match_mark_spec.rb diff --git a/README.markdown b/README.markdown index e4d11a39c..c2cc352dd 100644 --- a/README.markdown +++ b/README.markdown @@ -575,6 +575,8 @@ If Puppet is managing the iptables or iptables-persistent packages, and the prov * `month_days`: Only match on the given days of the month. Possible values are '1' to '31'. Note that specifying 31 will of course not match on months which do not have a 31st day; the same goes for 28- or 29-day February. +* `match_mark`: Match the Netfilter mark value associated with the packet. Accepts either of mark/mask or mark. These will be converted to hex if they are not already. Requires the `mark` feature. + * `mss`: Sets a given TCP MSS value or range to match. * `name`: The canonical name of the rule. This name is also used for ordering, so make sure you prefix the rule with a number. For example: diff --git a/lib/puppet/provider/firewall/ip6tables.rb b/lib/puppet/provider/firewall/ip6tables.rb index 196af39ab..1e2f2ed09 100644 --- a/lib/puppet/provider/firewall/ip6tables.rb +++ b/lib/puppet/provider/firewall/ip6tables.rb @@ -91,6 +91,7 @@ def self.iptables_save(*args) :log_level => "--log-level", :log_prefix => "--log-prefix", :mask => "--mask", + :match_mark => "-m mark --mark", :name => "-m comment --comment", :mac_source => ["-m mac --mac-source", "--mac-source"], :mss => "-m tcpmss --mss", @@ -216,6 +217,6 @@ def self.iptables_save(*args) :ctstate, :icmp, :hop_limit, :limit, :burst, :recent, :rseconds, :reap, :rhitcount, :rttl, :rname, :mask, :rsource, :rdest, :ipset, :jump, :gateway, :todest, :tosource, :toports, :checksum_fill, :log_level, :log_prefix, :reject, :set_mss, :mss, - :set_mark, :connlimit_above, :connlimit_mask, :connmark, :time_start, :time_stop, :month_days, :week_days, :date_start, :date_stop, :time_contiguous, :kernel_timezone] + :set_mark, :match_mark, :connlimit_above, :connlimit_mask, :connmark, :time_start, :time_stop, :month_days, :week_days, :date_start, :date_stop, :time_contiguous, :kernel_timezone] end diff --git a/lib/puppet/provider/firewall/iptables.rb b/lib/puppet/provider/firewall/iptables.rb index 30df7cf12..7557ac71a 100644 --- a/lib/puppet/provider/firewall/iptables.rb +++ b/lib/puppet/provider/firewall/iptables.rb @@ -75,6 +75,7 @@ :log_prefix => "--log-prefix", :mac_source => ["-m mac --mac-source", "--mac-source"], :mask => '--mask', + :match_mark => "-m mark --mark", :mss => '-m tcpmss --mss', :name => "-m comment --comment", :outiface => "-o", @@ -240,7 +241,7 @@ def munge_resource_map_from_resource(resource_map_original, compare) :src_type, :dst_type, :socket, :pkttype, :name, :ipsec_dir, :ipsec_policy, :state, :ctstate, :icmp, :limit, :burst, :recent, :rseconds, :reap, :rhitcount, :rttl, :rname, :mask, :rsource, :rdest, :ipset, :jump, :gateway, :set_mss, :todest, - :tosource, :toports, :to, :checksum_fill, :random, :log_prefix, :log_level, :reject, :set_mark, :mss, + :tosource, :toports, :to, :checksum_fill, :random, :log_prefix, :log_level, :reject, :set_mark, :match_mark, :mss, :connlimit_above, :connlimit_mask, :connmark, :time_start, :time_stop, :month_days, :week_days, :date_start, :date_stop, :time_contiguous, :kernel_timezone ] diff --git a/lib/puppet/type/firewall.rb b/lib/puppet/type/firewall.rb index 3b589fcc8..0994504cb 100644 --- a/lib/puppet/type/firewall.rb +++ b/lib/puppet/type/firewall.rb @@ -788,6 +788,36 @@ def insync?(is) EOS end + # match mark + newproperty(:match_mark, :required_features => :mark) do + desc <<-EOS + Match the Netfilter mark value associated with the packet. Accepts either of: + mark/mask or mark. These will be converted to hex if they are not already. + EOS + munge do |value| + mark_regex = %r{\A((?:0x)?[0-9A-F]+)(/)?((?:0x)?[0-9A-F]+)?\z}i + match = value.to_s.match(mark_regex) + if match.nil? + raise ArgumentError, "Match MARK value must be integer or hex between 0 and 0xffffffff" + end + mark = @resource.to_hex32(match[1]) + + # Values that can't be converted to hex. + # Or contain a trailing slash with no mask. + if mark.nil? or (mark and match[2] and match[3].nil?) + raise ArgumentError, "Match MARK value must be integer or hex between 0 and 0xffffffff" + end + + # There should not be a mask on match_mark + unless match[3].nil? + raise ArgumentError, "iptables does not support masks on MARK match rules" + end + value = mark + + value + end + end + newproperty(:set_mark, :required_features => :mark) do desc <<-EOS Set the Netfilter mark value associated with the packet. Accepts either of: diff --git a/spec/acceptance/match_mark_spec.rb b/spec/acceptance/match_mark_spec.rb new file mode 100644 index 000000000..98f4fc54d --- /dev/null +++ b/spec/acceptance/match_mark_spec.rb @@ -0,0 +1,53 @@ +require 'spec_helper_acceptance' + +describe 'firewall type', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do + + if default['platform'] !~ /el-5/ + describe 'match_mark' do + context '0x1' do + it 'applies' do + pp = <<-EOS + class { '::firewall': } + firewall { '503 match_mark - test': + proto => 'all', + match_mark => '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 "503 match_mark - test" -m mark --mark 0x1 -j REJECT --reject-with icmp-port-unreachable/) + end + end + end + end + + describe 'match_mark_ip6' do + context '0x1' do + it 'applies' do + pp = <<-EOS + class { '::firewall': } + firewall { '503 match_mark ip6tables - test': + proto => 'all', + match_mark => '0x1', + action => reject, + provider => 'ip6tables', + } + EOS + + apply_manifest(pp, :catch_failures => true) + end + + it 'should contain the rule' do + shell('ip6tables-save') do |r| + expect(r.stdout).to match(/-A INPUT -m comment --comment "503 match_mark ip6tables - test" -m mark --mark 0x1 -j REJECT --reject-with icmp6-port-unreachable/) + end + end + end + end + end +end diff --git a/spec/fixtures/iptables/conversion_hash.rb b/spec/fixtures/iptables/conversion_hash.rb index e33a2e13c..7ccaf48ea 100644 --- a/spec/fixtures/iptables/conversion_hash.rb +++ b/spec/fixtures/iptables/conversion_hash.rb @@ -543,6 +543,17 @@ :proto => 'udp', }, }, + 'match_mark' => { + :line => '-A INPUT -p tcp -m comment --comment "066 REJECT connlimit_above 10 with mask 32 and mark matches" -m mark --mark 0x1 -m connlimit --connlimit-above 10 --connlimit-mask 32 -j REJECT --reject-with icmp-port-unreachable', + :table => 'filter', + :params => { + :proto => 'tcp', + :connlimit_above => '10', + :connlimit_mask => '32', + :match_mark => '0x1', + :action => 'reject', + }, + }, } # This hash is for testing converting a hash to an argument line. @@ -1046,4 +1057,16 @@ }, :args => ["-t", :filter, "-s", "0.0.0.0/32", "-d", "255.255.255.255/32", "-p", :udp, "-m", "multiport", "!", "--sports", "68,69", "-m", "multiport", "!", "--dports", "67,66", "-m", "comment", "--comment", "065 negate dport and sport", "-j", "ACCEPT"], }, + 'match_mark' => { + :params => { + :name => '066 REJECT connlimit_above 10 with mask 32 and mark matches', + :table => 'filter', + :proto => 'tcp', + :connlimit_above => '10', + :connlimit_mask => '32', + :match_mark => '0x1', + :action => 'reject', + }, + :args => ["-t", :filter, "-p", :tcp, "-m", "comment", "--comment", "066 REJECT connlimit_above 10 with mask 32 and mark matches", "-j", "REJECT", "-m", "mark", "--mark", "0x1", "-m", "connlimit", "--connlimit-above", "10", "--connlimit-mask", "32"], + }, }