From: Jonas Truestedt Date: Thu, 22 Jun 2017 08:00:36 +0000 (+0200) Subject: added hashlimit-module for iptables & ip6tables with simple acceptance test X-Git-Tag: 1.10.0~19^2~1 X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=5b6de5030316dfd770f370b3dfcf92c0fd22974f;p=puppet-modules%2Fpuppetlabs-firewall.git added hashlimit-module for iptables & ip6tables with simple acceptance test --- diff --git a/lib/puppet/provider/firewall/ip6tables.rb b/lib/puppet/provider/firewall/ip6tables.rb index c8b3f64..c4b421c 100644 --- a/lib/puppet/provider/firewall/ip6tables.rb +++ b/lib/puppet/provider/firewall/ip6tables.rb @@ -70,93 +70,105 @@ Puppet::Type.type(:firewall).provide :ip6tables, :parent => :iptables, :source = @protocol = "IPv6" @resource_map = { - :burst => "--limit-burst", - :checksum_fill => "--checksum-fill", - :clamp_mss_to_pmtu => "--clamp-mss-to-pmtu", - :connlimit_above => "-m connlimit --connlimit-above", - :connlimit_mask => "--connlimit-mask", - :connmark => "-m connmark --mark", - :ctstate => "-m conntrack --ctstate", - :destination => "-d", - :dport => ["-m multiport --dports", "--dport"], - :dst_range => '--dst-range', - :dst_type => "--dst-type", - :gateway => "--gateway", - :gid => "--gid-owner", - :hop_limit => "-m hl --hl-eq", - :icmp => "-m icmp6 --icmpv6-type", - :iniface => "-i", - :ipsec_dir => "-m policy --dir", - :ipsec_policy => "--pol", - :ipset => "-m set --match-set", - :isfirstfrag => "-m frag --fragid 0 --fragfirst", - :ishasmorefrags => "-m frag --fragid 0 --fragmore", - :islastfrag => "-m frag --fragid 0 --fraglast", - :jump => "-j", - :length => "-m length --length", - :limit => "-m limit --limit", - :log_level => "--log-level", - :log_prefix => "--log-prefix", - :log_uid => "--log-uid", - :mask => "--mask", - :match_mark => "-m mark --mark", - :name => "-m comment --comment", - :mac_source => ["-m mac --mac-source", "--mac-source"], - :mss => "-m tcpmss --mss", - :outiface => "-o", - :pkttype => "-m pkttype --pkt-type", - :port => '-m multiport --ports', - :proto => "-p", - :queue_num => "--queue-num", - :queue_bypass => "--queue-bypass", - :rdest => "--rdest", - :reap => "--reap", - :recent => "-m recent", - :reject => "--reject-with", - :rhitcount => "--hitcount", - :rname => "--name", - :rseconds => "--seconds", - :rsource => "--rsource", - :rttl => "--rttl", - :set_dscp => '--set-dscp', - :set_dscp_class => '--set-dscp-class', - :set_mark => mark_flag, - :set_mss => '--set-mss', - :socket => "-m socket", - :source => "-s", - :sport => ["-m multiport --sports", "--sport"], - :src_range => '--src-range', - :src_type => "--src-type", - :stat_every => '--every', - :stat_mode => "-m statistic --mode", - :stat_packet => '--packet', - :stat_probability => '--probability', - :state => "-m state --state", - :string => "-m string --string", - :string_algo => "--algo", - :string_from => "--from", - :string_to => "--to", - :table => "-t", - :tcp_flags => "-m tcp --tcp-flags", - :todest => "--to-destination", - :toports => "--to-ports", - :tosource => "--to-source", - :uid => "--uid-owner", - :physdev_in => "--physdev-in", - :physdev_out => "--physdev-out", - :physdev_is_bridged => "--physdev-is-bridged", - :physdev_is_in => "--physdev-is-in", - :physdev_is_out => "--physdev-is-out", - :date_start => "--datestart", - :date_stop => "--datestop", - :time_start => "--timestart", - :time_stop => "--timestop", - :month_days => "--monthdays", - :week_days => "--weekdays", - :time_contiguous => "--contiguous", - :kernel_timezone => "--kerneltz", - :src_cc => "--source-country", - :dst_cc => "--destination-country", + :burst => "--limit-burst", + :checksum_fill => "--checksum-fill", + :clamp_mss_to_pmtu => "--clamp-mss-to-pmtu", + :connlimit_above => "-m connlimit --connlimit-above", + :connlimit_mask => "--connlimit-mask", + :connmark => "-m connmark --mark", + :ctstate => "-m conntrack --ctstate", + :destination => "-d", + :dport => ["-m multiport --dports", "--dport"], + :dst_range => '--dst-range', + :dst_type => "--dst-type", + :gateway => "--gateway", + :gid => "--gid-owner", + :hop_limit => "-m hl --hl-eq", + :icmp => "-m icmp6 --icmpv6-type", + :iniface => "-i", + :ipsec_dir => "-m policy --dir", + :ipsec_policy => "--pol", + :ipset => "-m set --match-set", + :isfirstfrag => "-m frag --fragid 0 --fragfirst", + :ishasmorefrags => "-m frag --fragid 0 --fragmore", + :islastfrag => "-m frag --fragid 0 --fraglast", + :jump => "-j", + :length => "-m length --length", + :limit => "-m limit --limit", + :log_level => "--log-level", + :log_prefix => "--log-prefix", + :log_uid => "--log-uid", + :mask => "--mask", + :match_mark => "-m mark --mark", + :name => "-m comment --comment", + :mac_source => ["-m mac --mac-source", "--mac-source"], + :mss => "-m tcpmss --mss", + :outiface => "-o", + :pkttype => "-m pkttype --pkt-type", + :port => '-m multiport --ports', + :proto => "-p", + :queue_num => "--queue-num", + :queue_bypass => "--queue-bypass", + :rdest => "--rdest", + :reap => "--reap", + :recent => "-m recent", + :reject => "--reject-with", + :rhitcount => "--hitcount", + :rname => "--name", + :rseconds => "--seconds", + :rsource => "--rsource", + :rttl => "--rttl", + :set_dscp => '--set-dscp', + :set_dscp_class => '--set-dscp-class', + :set_mark => mark_flag, + :set_mss => '--set-mss', + :socket => "-m socket", + :source => "-s", + :sport => ["-m multiport --sports", "--sport"], + :src_range => '--src-range', + :src_type => "--src-type", + :stat_every => '--every', + :stat_mode => "-m statistic --mode", + :stat_packet => '--packet', + :stat_probability => '--probability', + :state => "-m state --state", + :string => "-m string --string", + :string_algo => "--algo", + :string_from => "--from", + :string_to => "--to", + :table => "-t", + :tcp_flags => "-m tcp --tcp-flags", + :todest => "--to-destination", + :toports => "--to-ports", + :tosource => "--to-source", + :uid => "--uid-owner", + :physdev_in => "--physdev-in", + :physdev_out => "--physdev-out", + :physdev_is_bridged => "--physdev-is-bridged", + :physdev_is_in => "--physdev-is-in", + :physdev_is_out => "--physdev-is-out", + :date_start => "--datestart", + :date_stop => "--datestop", + :time_start => "--timestart", + :time_stop => "--timestop", + :month_days => "--monthdays", + :week_days => "--weekdays", + :time_contiguous => "--contiguous", + :kernel_timezone => "--kerneltz", + :src_cc => "--source-country", + :dst_cc => "--destination-country", + :hashlimit_name => "--hashlimit-name", + :hashlimit_upto => "--hashlimit-upto", + :hashlimit_above => "--hashlimit-above", + :hashlimit_burst => "--hashlimit-burst", + :hashlimit_mode => "--hashlimit-mode", + :hashlimit_srcmask => "--hashlimit-srcmask", + :hashlimit_dstmask => "--hashlimit-dstmask", + :hashlimit_htable_size => "--hashlimit-htable-size", + :hashlimit_htable_max => "--hashlimit-htable-max", + :hashlimit_htable_expire => "--hashlimit-htable-expire", + :hashlimit_htable_gcinterval => "--hashlimit-htable-gcinterval", + } # These are known booleans that do not take a value, but we want to munge @@ -199,7 +211,10 @@ Puppet::Type.type(:firewall).provide :ip6tables, :parent => :iptables, :source = :iprange => [:src_range, :dst_range], :owner => [:uid, :gid], :time => [:time_start, :time_stop, :month_days, :week_days, :date_start, :date_stop, :time_contiguous, :kernel_timezone], - :geoip => [:src_cc, :dst_cc] + :geoip => [:src_cc, :dst_cc], + :hashlimit => [:hashlimit_upto, :hashlimit_above, :hashlimit_name, :hashlimit_burst, :hashlimit_mode, :hashlimit_srcmask, :hashlimit_dstmask, + :hashlimit_htable_size, :hashlimit_htable_max, :hashlimit_htable_expire, :hashlimit_htable_gcinterval], + } # Create property methods dynamically @@ -246,6 +261,8 @@ Puppet::Type.type(:firewall).provide :ip6tables, :parent => :iptables, :source = :string_from, :string_to, :jump, :clamp_mss_to_pmtu, :gateway, :todest, :tosource, :toports, :checksum_fill, :log_level, :log_prefix, :log_uid, :reject, :set_mss, :set_dscp, :set_dscp_class, :mss, :queue_num, :queue_bypass, :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, - :src_cc, :dst_cc, :name] + :src_cc, :dst_cc, :hashlimit_upto, :hashlimit_above, :hashlimit_name, :hashlimit_burst, + :hashlimit_mode, :hashlimit_srcmask, :hashlimit_dstmask, :hashlimit_htable_size, + :hashlimit_htable_max, :hashlimit_htable_expire, :hashlimit_htable_gcinterval, :name] end diff --git a/lib/puppet/provider/firewall/iptables.rb b/lib/puppet/provider/firewall/iptables.rb index b05ba43..1c847d7 100644 --- a/lib/puppet/provider/firewall/iptables.rb +++ b/lib/puppet/provider/firewall/iptables.rb @@ -61,103 +61,114 @@ Puppet::Type.type(:firewall).provide :iptables, :parent => Puppet::Provider::Fir @protocol = "IPv4" @resource_map = { - :burst => "--limit-burst", - :checksum_fill => "--checksum-fill", - :clamp_mss_to_pmtu => "--clamp-mss-to-pmtu", - :connlimit_above => "-m connlimit --connlimit-above", - :connlimit_mask => "--connlimit-mask", - :connmark => "-m connmark --mark", - :ctstate => "-m conntrack --ctstate", - :destination => "-d", - :dport => ["-m multiport --dports", "--dport"], - :dst_range => "--dst-range", - :dst_type => "--dst-type", - :gateway => "--gateway", - :gid => "--gid-owner", - :icmp => "-m icmp --icmp-type", - :iniface => "-i", - :ipsec_dir => "-m policy --dir", - :ipsec_policy => "--pol", - :ipset => "-m set --match-set", - :isfragment => "-f", - :jump => "-j", - :goto => "-g", - :length => "-m length --length", - :limit => "-m limit --limit", - :log_level => "--log-level", - :log_prefix => "--log-prefix", - :log_uid => "--log-uid", - :mac_source => ["-m mac --mac-source", "--mac-source"], - :mask => '--mask', - :match_mark => "-m mark --mark", - :mss => '-m tcpmss --mss', - :name => "-m comment --comment", - :nflog_group => "--nflog-group", - :nflog_prefix => "--nflog-prefix", - :nflog_range => "--nflog-range", - :nflog_threshold => "--nflog-threshold", - :outiface => "-o", - :pkttype => "-m pkttype --pkt-type", - :port => '-m multiport --ports', - :proto => "-p", - :queue_num => "--queue-num", - :queue_bypass => "--queue-bypass", - :random => "--random", - :rdest => "--rdest", - :reap => "--reap", - :recent => "-m recent", - :reject => "--reject-with", - :rhitcount => "--hitcount", - :rname => "--name", - :rseconds => "--seconds", - :rsource => "--rsource", - :rttl => "--rttl", - :set_dscp => '--set-dscp', - :set_dscp_class => '--set-dscp-class', - :set_mark => mark_flag, - :set_mss => '--set-mss', - :socket => "-m socket", - :source => "-s", - :sport => ["-m multiport --sports", "--sport"], - :src_range => "--src-range", - :src_type => "--src-type", - :stat_every => '--every', - :stat_mode => "-m statistic --mode", - :stat_packet => '--packet', - :stat_probability => '--probability', - :state => "-m state --state", - :string => "-m string --string", - :string_algo => "--algo", - :string_from => "--from", - :string_to => "--to", - :table => "-t", - :tcp_flags => "-m tcp --tcp-flags", - :todest => "--to-destination", - :toports => "--to-ports", - :tosource => "--to-source", - :to => "--to", - :uid => "--uid-owner", - :physdev_in => "--physdev-in", - :physdev_out => "--physdev-out", - :physdev_is_bridged => "--physdev-is-bridged", - :physdev_is_in => "--physdev-is-in", - :physdev_is_out => "--physdev-is-out", - :date_start => "--datestart", - :date_stop => "--datestop", - :time_start => "--timestart", - :time_stop => "--timestop", - :month_days => "--monthdays", - :week_days => "--weekdays", - :time_contiguous => "--contiguous", - :kernel_timezone => "--kerneltz", - :clusterip_new => "--new", - :clusterip_hashmode => "--hashmode", - :clusterip_clustermac => "--clustermac", - :clusterip_total_nodes => "--total-nodes", - :clusterip_local_node => "--local-node", - :clusterip_hash_init => "--hash-init", - :src_cc => "--source-country", - :dst_cc => "--destination-country", + :burst => "--limit-burst", + :checksum_fill => "--checksum-fill", + :clamp_mss_to_pmtu => "--clamp-mss-to-pmtu", + :connlimit_above => "-m connlimit --connlimit-above", + :connlimit_mask => "--connlimit-mask", + :connmark => "-m connmark --mark", + :ctstate => "-m conntrack --ctstate", + :destination => "-d", + :dport => ["-m multiport --dports", "--dport"], + :dst_range => "--dst-range", + :dst_type => "--dst-type", + :gateway => "--gateway", + :gid => "--gid-owner", + :icmp => "-m icmp --icmp-type", + :iniface => "-i", + :ipsec_dir => "-m policy --dir", + :ipsec_policy => "--pol", + :ipset => "-m set --match-set", + :isfragment => "-f", + :jump => "-j", + :goto => "-g", + :length => "-m length --length", + :limit => "-m limit --limit", + :log_level => "--log-level", + :log_prefix => "--log-prefix", + :log_uid => "--log-uid", + :mac_source => ["-m mac --mac-source", "--mac-source"], + :mask => '--mask', + :match_mark => "-m mark --mark", + :mss => '-m tcpmss --mss', + :name => "-m comment --comment", + :nflog_group => "--nflog-group", + :nflog_prefix => "--nflog-prefix", + :nflog_range => "--nflog-range", + :nflog_threshold => "--nflog-threshold", + :outiface => "-o", + :pkttype => "-m pkttype --pkt-type", + :port => '-m multiport --ports', + :proto => "-p", + :queue_num => "--queue-num", + :queue_bypass => "--queue-bypass", + :random => "--random", + :rdest => "--rdest", + :reap => "--reap", + :recent => "-m recent", + :reject => "--reject-with", + :rhitcount => "--hitcount", + :rname => "--name", + :rseconds => "--seconds", + :rsource => "--rsource", + :rttl => "--rttl", + :set_dscp => '--set-dscp', + :set_dscp_class => '--set-dscp-class', + :set_mark => mark_flag, + :set_mss => '--set-mss', + :socket => "-m socket", + :source => "-s", + :sport => ["-m multiport --sports", "--sport"], + :src_range => "--src-range", + :src_type => "--src-type", + :stat_every => '--every', + :stat_mode => "-m statistic --mode", + :stat_packet => '--packet', + :stat_probability => '--probability', + :state => "-m state --state", + :string => "-m string --string", + :string_algo => "--algo", + :string_from => "--from", + :string_to => "--to", + :table => "-t", + :tcp_flags => "-m tcp --tcp-flags", + :todest => "--to-destination", + :toports => "--to-ports", + :tosource => "--to-source", + :to => "--to", + :uid => "--uid-owner", + :physdev_in => "--physdev-in", + :physdev_out => "--physdev-out", + :physdev_is_bridged => "--physdev-is-bridged", + :physdev_is_in => "--physdev-is-in", + :physdev_is_out => "--physdev-is-out", + :date_start => "--datestart", + :date_stop => "--datestop", + :time_start => "--timestart", + :time_stop => "--timestop", + :month_days => "--monthdays", + :week_days => "--weekdays", + :time_contiguous => "--contiguous", + :kernel_timezone => "--kerneltz", + :clusterip_new => "--new", + :clusterip_hashmode => "--hashmode", + :clusterip_clustermac => "--clustermac", + :clusterip_total_nodes => "--total-nodes", + :clusterip_local_node => "--local-node", + :clusterip_hash_init => "--hash-init", + :src_cc => "--source-country", + :dst_cc => "--destination-country", + :hashlimit_name => "--hashlimit-name", + :hashlimit_upto => "--hashlimit-upto", + :hashlimit_above => "--hashlimit-above", + :hashlimit_burst => "--hashlimit-burst", + :hashlimit_mode => "--hashlimit-mode", + :hashlimit_srcmask => "--hashlimit-srcmask", + :hashlimit_dstmask => "--hashlimit-dstmask", + :hashlimit_htable_size => "--hashlimit-htable-size", + :hashlimit_htable_max => "--hashlimit-htable-max", + :hashlimit_htable_expire => "--hashlimit-htable-expire", + :hashlimit_htable_gcinterval => "--hashlimit-htable-gcinterval", } # These are known booleans that do not take a value, but we want to munge @@ -200,7 +211,9 @@ Puppet::Type.type(:firewall).provide :iptables, :parent => Puppet::Provider::Fir :iprange => [:src_range, :dst_range], :owner => [:uid, :gid], :time => [:time_start, :time_stop, :month_days, :week_days, :date_start, :date_stop, :time_contiguous, :kernel_timezone], - :geoip => [:src_cc, :dst_cc] + :geoip => [:src_cc, :dst_cc], + :hashlimit => [:hashlimit_upto, :hashlimit_above, :hashlimit_name, :hashlimit_burst, :hashlimit_mode, :hashlimit_srcmask, :hashlimit_dstmask, + :hashlimit_htable_size, :hashlimit_htable_max, :hashlimit_htable_expire, :hashlimit_htable_gcinterval], } def self.munge_resource_map_from_existing_values(resource_map_original, compare) @@ -291,7 +304,9 @@ Puppet::Type.type(:firewall).provide :iptables, :parent => Puppet::Provider::Fir :set_mss, :set_dscp, :set_dscp_class, :todest, :tosource, :toports, :to, :checksum_fill, :random, :log_prefix, :log_level, :log_uid, :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, - :src_cc, :dst_cc, :name] + :src_cc, :dst_cc, :hashlimit_upto, :hashlimit_above, :hashlimit_name, :hashlimit_burst, + :hashlimit_mode, :hashlimit_srcmask, :hashlimit_dstmask, :hashlimit_htable_size, + :hashlimit_htable_max, :hashlimit_htable_expire, :hashlimit_htable_gcinterval, :name] def insert debug 'Inserting rule %s' % resource[:name] diff --git a/lib/puppet/type/firewall.rb b/lib/puppet/type/firewall.rb index 6deab2b..981fdb9 100644 --- a/lib/puppet/type/firewall.rb +++ b/lib/puppet/type/firewall.rb @@ -67,6 +67,7 @@ Puppet::Type.newtype(:firewall) do feature :string_matching, "String matching features" feature :queue_num, "Which NFQUEUE to send packets to" feature :queue_bypass, "If nothing is listening on queue_num, allow packets to bypass the queue" + feature :hashlimit, "Hashlimit features" # provider specific features feature :iptables, "The provider provides iptables features." @@ -1589,6 +1590,79 @@ Puppet::Type.newtype(:firewall) do newvalues(/^[A-Z]{2}(,[A-Z]{2})*$/) end + newproperty(:hashlimit_name) do + desc <<-EOS + The name for the /proc/net/ipt_hashlimit/foo entry. + This parameter is required. + EOS + end + + newproperty(:hashlimit_upto) do + desc <<-EOS + Match if the rate is below or equal to amount/quantum. It is specified either as a number, with an optional time quantum suffix (the default is 3/hour), or as amountb/second (number of bytes per second). + This parameter or hashlimit_above is required. + Allowed forms are '40','40/second','40/minute','40/hour','40/day'. + EOS + end + + newproperty(:hashlimit_above) do + desc <<-EOS + Match if the rate is above amount/quantum. + This parameter or hashlimit_upto is required. + Allowed forms are '40','40/second','40/minute','40/hour','40/day'. + EOS + end + + newproperty(:hashlimit_burst) do + desc <<-EOS + Maximum initial number of packets to match: this number gets recharged by one every time the limit specified above is not reached, up to this number; the default is 5. When byte-based rate matching is requested, this option specifies the amount of bytes that can exceed the given rate. This option should be used with caution -- if the entry expires, the burst value is reset too. + EOS + newvalue(/^\d+$/) + end + + newproperty(:hashlimit_mode) do + desc <<-EOS + A comma-separated list of objects to take into consideration. If no --hashlimit-mode option is given, hashlimit acts like limit, but at the expensive of doing the hash housekeeping. + Allowed values are: srcip, srcport, dstip, dstport + EOS + end + + newproperty(:hashlimit_srcmask) do + desc <<-EOS + When --hashlimit-mode srcip is used, all source addresses encountered will be grouped according to the given prefix length and the so-created subnet will be subject to hashlimit. prefix must be between (inclusive) 0 and 32. Note that --hashlimit-srcmask 0 is basically doing the same thing as not specifying srcip for --hashlimit-mode, but is technically more expensive. + EOS + end + + newproperty(:hashlimit_dstmask) do + desc <<-EOS + Like --hashlimit-srcmask, but for destination addresses. + EOS + end + + newproperty(:hashlimit_htable_size) do + desc <<-EOS + The number of buckets of the hash table + EOS + end + + newproperty(:hashlimit_htable_max) do + desc <<-EOS + Maximum entries in the hash. + EOS + end + + newproperty(:hashlimit_htable_expire) do + desc <<-EOS + After how many milliseconds do hash entries expire. + EOS + end + + newproperty(:hashlimit_htable_gcinterval) do + desc <<-EOS + How many milliseconds between garbage collection intervals. + EOS + end + autorequire(:firewallchain) do reqs = [] protocol = nil @@ -1794,5 +1868,10 @@ Puppet::Type.newtype(:firewall) do end end + if value(:hashlimit_name) + unless value(:hashlimit_upto) || value(:hashlimit_above) + self.fail "Either hashlimit_upto or hashlimit_above are required" + end + end end end diff --git a/spec/acceptance/hashlimit_spec.rb b/spec/acceptance/hashlimit_spec.rb new file mode 100644 index 0000000..303dd81 --- /dev/null +++ b/spec/acceptance/hashlimit_spec.rb @@ -0,0 +1,121 @@ + +require 'spec_helper_acceptance' + +describe 'hashlimit property' do + before :all do + iptables_flush_all_tables + ip6tables_flush_all_tables + end + + describe 'hashlimit_tests' do + context 'hashlimit_above' do + it 'applies' do + pp = <<-EOS + class { '::firewall': } + firewall { '800 - hashlimit_above test': + chain => 'INPUT', + proto => 'tcp', + hashlimit_name => 'above', + hashlimit_above => '512kb/s', + hashlimit_htable_gcinterval => '10', + hashlimit_mode => 'srcip,dstip', + action => accept, + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => do_catch_changes) + end + + it 'should contain the rule' do + shell('iptables-save') do |r| + expect(r.stdout).to match(/-A INPUT -p tcp -m hashlimit --hashlimit-above 512kb\/s --hashlimit-mode srcip,dstip --hashlimit-name above --hashlimit-htable-gcinterval 10 -m comment --comment "800 - hashlimit_above test" -j ACCEPT/) + end + end + end + + context 'hashlimit_above_ip6' do + it 'applies' do + pp = <<-EOS + class { '::firewall': } + firewall { '801 - hashlimit_above test ipv6': + chain => 'INPUT', + provider => 'ip6tables', + proto => 'tcp', + hashlimit_name => 'above-ip6', + hashlimit_above => '512kb/s', + hashlimit_htable_gcinterval => '10', + hashlimit_mode => 'srcip,dstip', + action => accept, + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => do_catch_changes) + end + + it 'should contain the rule' do + shell('ip6tables-save') do |r| + expect(r.stdout).to match(/-A INPUT -p tcp -m hashlimit --hashlimit-above 512kb\/s --hashlimit-mode srcip,dstip --hashlimit-name above-ip6 --hashlimit-htable-gcinterval 10 -m comment --comment "801 - hashlimit_above test ipv6" -j ACCEPT/) + end + end + end + + context 'hashlimit_upto' do + it 'applies' do + pp = <<-EOS + class { '::firewall': } + firewall { '802 - hashlimit_upto test': + chain => 'INPUT', + hashlimit_name => 'upto', + hashlimit_upto => '16/sec', + hashlimit_burst => '640', + hashlimit_htable_size => '1310000', + hashlimit_htable_max => '320000', + hashlimit_htable_expire => '36000000', + action => accept, + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => do_catch_changes) + end + + it 'should contain the rule' do + shell('iptables-save') do |r| + expect(r.stdout).to match(/-A INPUT -p tcp -m hashlimit --hashlimit-upto 16\/sec --hashlimit-burst 640 --hashlimit-name upto --hashlimit-htable-size 1310000 --hashlimit-htable-max 320000 --hashlimit-htable-expire 36000000 -m comment --comment "802 - hashlimit_upto test" -j ACCEPT/) + end + end + end + + context 'hashlimit_upto_ip6' do + it 'applies' do + pp = <<-EOS + class { '::firewall': } + firewall { '803 - hashlimit_upto test ip6': + chain => 'INPUT', + provider => 'ip6tables', + hashlimit_name => 'upto-ip6', + hashlimit_upto => '16/sec', + hashlimit_burst => '640', + hashlimit_htable_size => '1310000', + hashlimit_htable_max => '320000', + hashlimit_htable_expire => '36000000', + action => accept, + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => do_catch_changes) + end + + it 'should contain the rule' do + shell('ip6tables-save') do |r| + expect(r.stdout).to match(/-A INPUT -p tcp -m hashlimit --hashlimit-upto 16\/sec --hashlimit-burst 640 --hashlimit-name upto-ip6 --hashlimit-htable-size 1310000 --hashlimit-htable-max 320000 --hashlimit-htable-expire 36000000 -m comment --comment "803 - hashlimit_upto test ip6" -j ACCEPT/) + end + end + end + + end + +end