]> review.fuel-infra Code Review - puppet-modules/puppetlabs-firewall.git/commitdiff
add set_dscp and set_dscp_class
authorEric Stonfer <ericstonfer@yahoo.com>
Wed, 15 Jul 2015 17:16:06 +0000 (13:16 -0400)
committerEric Stonfer <ericstonfer@yahoo.com>
Wed, 15 Jul 2015 17:16:06 +0000 (13:16 -0400)
README.markdown
lib/puppet/provider/firewall/ip6tables.rb
lib/puppet/provider/firewall/iptables.rb
lib/puppet/type/firewall.rb
spec/acceptance/firewall_dscp_spec.rb [new file with mode: 0644]
spec/fixtures/iptables/conversion_hash.rb
spec/unit/puppet/provider/iptables_spec.rb

index 40fe873e108eecc005516bf37f439cbf0669f586..c770f3c5268850016a5c95d5291628679ec68cad 100644 (file)
@@ -574,7 +574,7 @@ If Puppet is managing the iptables or iptables-persistent packages, and the prov
 
 * `islastfrag`: If true, matches when the packet is the last fragment of a fragmented ipv6 packet. Supported by ipv6 only. Valid values are 'true', 'false'. Requires the `islastfrag`.
 
-* `jump`: The value for the iptables `--jump` parameter. Any valid chain name is allowed, but normal values are: 'QUEUE', 'RETURN', 'DNAT', 'SNAT', 'LOG', 'MASQUERADE', 'REDIRECT', 'MARK', 'TCPMSS'.
+* `jump`: The value for the iptables `--jump` parameter. Any valid chain name is allowed, but normal values are: 'QUEUE', 'RETURN', 'DNAT', 'SNAT', 'LOG', 'MASQUERADE', 'REDIRECT', 'MARK', 'TCPMSS', 'DSCP'.
 
   For the values 'ACCEPT', 'DROP', and 'REJECT', you must use the generic `action` parameter. This is to enforce the use of generic parameters where possible for maximum cross-platform modeling.
 
@@ -687,6 +687,10 @@ firewall { '101 blacklist strange traffic':
 
 * `rttl`: May only be used in conjunction with `recent => 'rcheck'` or `recent => 'update'`. If boolean 'true', this will narrow the match to happen only when the address is in the list and the TTL of the current packet matches that of the packet that hit the `recent => 'set'` rule. If you have problems with DoS attacks via bogus packets from fake source addresses, this parameter may help. Valid values are 'true', 'false'. Requires the `recent_limiting` feature and the `recent` parameter.
 
+* `set_dscp`: When combined with `jump => 'DSCP'` specifies the dscp marking associated with the packet.
+
+* `set_dscp_class`: When combined with `jump => 'DSCP'` specifies the class associated with the packet (valid values found here: http://www.cisco.com/c/en/us/support/docs/quality-of-service-qos/qos-packet-marking/10103-dscpvalues.html#packetclassification).
+
 * `set_mark`: Set the Netfilter mark value associated with the packet. Accepts either  'mark/mask' or 'mark'. These will be converted to hex if they are not already. Requires the `mark` feature.
 
 * `set_mss`: When combined with `jump => 'TCPMSS'` specifies the value of the MSS field.
index 2a05dcf69753a5627d45257bf65d972554d8a123..585f855ebbfe6dbe3d76bbd7ed8e43e85300ce49 100644 (file)
@@ -109,6 +109,8 @@ Puppet::Type.type(:firewall).provide :ip6tables, :parent => :iptables, :source =
     :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",
@@ -218,7 +220,7 @@ Puppet::Type.type(:firewall).provide :ip6tables, :parent => :iptables, :source =
     :dst_type, :socket, :pkttype, :name, :ipsec_dir, :ipsec_policy, :state,
     :ctstate, :icmp, :hop_limit, :limit, :burst, :recent, :rseconds, :reap,
     :rhitcount, :rttl, :rname, :mask, :rsource, :rdest, :ipset, :jump, :clamp_mss_to_pmtu, :gateway, :todest,
-    :tosource, :toports, :checksum_fill, :log_level, :log_prefix, :reject, :set_mss, :mss,
+    :tosource, :toports, :checksum_fill, :log_level, :log_prefix, :reject, :set_mss, :set_dscp, :set_dscp_class, :mss,
     :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
index 3c1bec4e7e3b4defec46eba8c9405b882f905f65..52a7a2da6680eb01b494aabb692808b867b5d68b 100644 (file)
@@ -94,6 +94,8 @@ Puppet::Type.type(:firewall).provide :iptables, :parent => Puppet::Provider::Fir
     :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",
@@ -252,7 +254,7 @@ Puppet::Type.type(:firewall).provide :iptables, :parent => Puppet::Provider::Fir
     :state, :ctstate, :icmp, :limit, :burst, :recent, :rseconds, :reap,
     :rhitcount, :rttl, :rname, :mask, :rsource, :rdest, :ipset, :jump, :clusterip_new, :clusterip_hashmode,
     :clusterip_clustermac, :clusterip_total_nodes, :clusterip_local_node, :clusterip_hash_init,
-    :clamp_mss_to_pmtu, :gateway, :set_mss, :todest, :tosource, :toports, :to, :checksum_fill, :random, :log_prefix,
+    :clamp_mss_to_pmtu, :gateway, :set_mss, :set_dscp, :set_dscp_class, :todest, :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
   ]
@@ -412,6 +414,37 @@ Puppet::Type.type(:firewall).provide :iptables, :parent => Puppet::Provider::Fir
     [:dport, :sport, :port, :state, :ctstate].each do |prop|
       hash[prop] = hash[prop].split(',') if ! hash[prop].nil?
     end
+  
+    ## clean up DSCP class to HEX mappings 
+    valid_dscp_classes = {
+      '0x0a' => 'af11',
+      '0x0c' => 'af12',
+      '0x0e' => 'af13',
+      '0x12' => 'af21',
+      '0x14' => 'af22',
+      '0x16' => 'af23',
+      '0x1a' => 'af31',
+      '0x1c' => 'af32',
+      '0x1e' => 'af33',
+      '0x22' => 'af41',
+      '0x24' => 'af42',
+      '0x26' => 'af43',
+      '0x08' => 'cs1',
+      '0x10' => 'cs2',
+      '0x18' => 'cs3',
+      '0x20' => 'cs4',
+      '0x28' => 'cs5',
+      '0x30' => 'cs6',
+      '0x38' => 'cs7',
+      '0x2e' => 'ef'
+    }
+    [:set_dscp_class].each do |prop|
+      [:set_dscp].each do |dmark|
+        next unless hash[dmark]
+        hash[prop] = valid_dscp_classes[hash[dmark]]
+     end
+    end
+
 
     # Convert booleans removing the previous cludge we did
     @known_booleans.each do |bool|
@@ -515,7 +548,6 @@ Puppet::Type.type(:firewall).provide :iptables, :parent => Puppet::Provider::Fir
       hash[:action] = hash[:jump].downcase
       hash.delete(:jump)
     end
-
     hash
   end
 
index 35c699b03e46e449032a4916b2a21cc399d4bb64..171c2e6f1b069ef8d560e7b153ffd44a123a08a5 100644 (file)
@@ -873,6 +873,30 @@ Puppet::Type.newtype(:firewall) do
     newvalues(:true, :false)
   end
 
+  newproperty(:set_dscp, :required_features => :iptables) do
+    desc <<-EOS
+      Set DSCP Markings.
+    EOS
+  end
+  
+  newproperty(:set_dscp_class, :required_features => :iptables) do
+    desc <<-EOS
+      This sets the DSCP field according to a predefined DiffServ class.
+    EOS
+    #  iptables uses the cisco DSCP classes as the basis for this flag. Values may be found here:
+    #  'http://www.cisco.com/c/en/us/support/docs/quality-of-service-qos/qos-packet-marking/10103-dscpvalues.html'
+    valid_codes = [
+      'af11','af12','af13','af21','af22','af23','af31','af32','af33','af41',
+      'af42','af43','cs1','cs2','cs3','cs4','cs5','cs6','cs7','ef'
+    ]
+    munge do |value|
+      unless valid_codes.include? value.downcase
+        raise ArgumentError, "#{value} is not a valid DSCP Class"
+      end
+      value.downcase
+    end
+  end
+
   newproperty(:set_mss, :required_features => :iptables) do
     desc <<-EOS
       Sets the TCP MSS value for packets.
@@ -1414,6 +1438,12 @@ Puppet::Type.newtype(:firewall) do
       end
     end
 
+    if value(:jump).to_s == "DSCP"
+      unless value(:set_dscp) || value(:set_dscp_class)
+        self.fail "When using jump => DSCP, the set_dscp or set_dscp_class property is required"
+      end
+    end
+
     if value(:jump).to_s == "TCPMSS"
       unless value(:set_mss) || value(:clamp_mss_to_pmtu)
         self.fail "When using jump => TCPMSS, the set_mss or clamp_mss_to_pmtu property is required"
diff --git a/spec/acceptance/firewall_dscp_spec.rb b/spec/acceptance/firewall_dscp_spec.rb
new file mode 100644 (file)
index 0000000..bbb68ef
--- /dev/null
@@ -0,0 +1,118 @@
+require 'spec_helper_acceptance'
+
+describe 'firewall type', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+
+  before(:all) do
+    shell('iptables --flush; iptables -t nat --flush; iptables -t mangle --flush')
+    shell('ip6tables --flush; ip6tables -t nat --flush; ip6tables -t mangle --flush')
+  end
+
+  describe 'dscp ipv4 tests' do
+    context 'set_dscp 0x01' do
+      it 'applies' do
+        pp = <<-EOS
+          class { '::firewall': }
+          firewall {
+            '1000 - set_dscp':
+              proto     => 'tcp',
+              jump      => 'DSCP',
+              set_dscp  => '0x01',
+              port      => '997',
+              chain     => 'OUTPUT',
+              table     => 'mangle',
+          }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      it 'should contain the rule' do
+        shell('iptables-save -t mangle') do |r|
+          expect(r.stdout).to match(/-A OUTPUT -p tcp -m multiport --ports 997 -m comment --comment "1000 - set_dscp" -j DSCP --set-dscp 0x01/)
+        end
+      end
+    end
+
+    context 'set_dscp_class EF' do
+      it 'applies' do
+        pp = <<-EOS
+          class { '::firewall': }
+          firewall {
+            '1001 EF - set_dscp_class':
+              proto          => 'tcp',
+              jump           => 'DSCP',
+              port           => '997',
+              set_dscp_class => 'EF',
+              chain          => 'OUTPUT',
+              table          => 'mangle',
+          }
+        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 OUTPUT -p tcp -m multiport --ports 997 -m comment --comment "1001 EF - set_dscp_class" -j DSCP --set-dscp 0x2e/)
+        end
+      end
+    end
+  end
+
+  if default['platform'] !~ /el-5/
+    describe 'dscp ipv6 tests' do
+      context 'set_dscp 0x01' do
+        it 'applies' do
+          pp = <<-EOS
+            class { '::firewall': }
+            firewall {
+              '1002 - set_dscp':
+                proto     => 'tcp',
+                jump      => 'DSCP',
+                set_dscp  => '0x01',
+                port      => '997',
+                chain     => 'OUTPUT',
+                table     => 'mangle',
+                provider  => 'ip6tables',
+            }
+          EOS
+
+          apply_manifest(pp, :catch_failures => true)
+        end
+
+        it 'should contain the rule' do
+          shell('ip6tables-save -t mangle') do |r|
+            expect(r.stdout).to match(/-A OUTPUT -p tcp -m multiport --ports 997 -m comment --comment "1002 - set_dscp" -j DSCP --set-dscp 0x01/)
+          end
+        end
+      end
+
+      context 'set_dscp_class EF' do
+        it 'applies' do
+          pp = <<-EOS
+            class { '::firewall': }
+            firewall {
+              '1003 EF - set_dscp_class':
+                proto          => 'tcp',
+                jump           => 'DSCP',
+                port           => '997',
+                set_dscp_class => 'EF',
+                chain          => 'OUTPUT',
+                table          => 'mangle',
+                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 OUTPUT -p tcp -m multiport --ports 997 -m comment --comment "1003 EF - set_dscp_class" -j DSCP --set-dscp 0x2e/)
+          end
+        end
+      end
+    end
+  end
+
+end
index 28858eba1254a0f134f00652a92c02d2b9be4a90..d6db2787eaf47722cbefd6e5a6f47bec29bd667d 100644 (file)
@@ -1106,4 +1106,15 @@ HASH_TO_ARGS = {
     },
     :args => ["-t", :filter, "-p", :tcp, "-m", "tcp", "--tcp-flags", "SYN,RST", "SYN", "-m", "comment", "--comment", "067 change max segment size", "-j", "TCPMSS", "--clamp-mss-to-pmtu"],
   },
+  'set_dscp_class' => {
+    :params => {
+      :name              => '068 set dscp class to EF',
+      :table             => 'mangle',
+      :proto             => 'tcp',
+      :port              => '997',
+      :jump              => 'DSCP',
+      :set_dscp_class    => 'ef',
+    },
+    :args => ["-t", :mangle, "-p", :tcp, "-m", "multiport", '--ports', '997', "-m", "comment", "--comment", "068 set dscp class to EF", "-j", "DSCP", "--set-dscp-class", "ef"],
+  },
 }
index e73bf84ad6309041bd8a09bdfbca80d092c7283b..055707196a7507e0242c1ecad1ceb2a09e8f5ac3 100644 (file)
@@ -215,7 +215,6 @@ describe 'iptables provider' 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